routing路由
ES在添加数据时,会根据id或者routing参数进行hash,得到hash值再与该索引库的分片数量取模,得到的值即为存入的分片编号。如果多条数据使用相同的routing,那么最终计算出来的分片编号都是一样的,那么这些数据就可以存储到相同的分片里面了。后期查询的只需要到指定分片中查询即可,可以显著提高查询性能。
如果在面试的时候面试官问你如何在ES中实现极速查询,其实就是问这个routing路由功能。
下面来演示一下: 创建一个新的索引库,指定5个分片,0个副本。
curl -H "Content-Type: application/json" -XPUT 'http://master:9200/rout/' -d'{"settings":{"number_of_shards":5,"number_of_replicas":0}}'
初始化数据:
curl -H "Content-Type: application/json" -XPOST 'http://master:9200/rout/_doc/1?routing=class1' -d'{"name":"tom","age":18}'
curl -H "Content-Type: application/json" -XPOST 'http://master:9200/rout/_doc/2?routing=class1' -d'{"name":"jack","age":29}'
curl -H "Content-Type: application/json" -XPOST 'http://master:9200/rout/_doc/3?routing=class1' -d'{"name":"jessica","age":18}'
curl -H "Content-Type: application/json" -XPOST 'http://master:9200/rout/_doc/4?routing=class1' -d'{"name":"dave","age":19}'
curl -H "Content-Type: application/json" -XPOST 'http://master:9200/rout/_doc/5?routing=class1' -d'{"name":"lilei","age":18}'
curl -H "Content-Type: application/json" -XPOST 'http://master:9200/rout/_doc/6?routing=class1' -d'{"name":"lili","age":29}'
curl -H "Content-Type: application/json" -XPOST 'http://master:9200/rout/_doc/7?routing=class1' -d'{"name":"simoni","age":28}'
curl -H "Content-Type: application/json" -XPOST 'http://master:9200/rout/_doc/7?routing=class1' -d'{"name":"anthony","age":22}'
如果是使用的JavaAPI,那么需要通过使用routing函数指定。
private static void addIndexByJson(RestHighLevelClient client) throws IOException {
IndexRequest request = new IndexRequest("emp");
request.id("10");
String jsonString = "{" +
"\"name\":\"jessic\"," +
"\"age\":20" +
"}";
request.source(jsonString, XContentType.JSON);
request.routing("class1");
//执行
client.index(request, RequestOptions.DEFAULT);
}
查看数据在分片中的分布情况,发现所有数据都在0号分片里面,说明routing参数生效了。

java代码实现:
package com.simoniu.db_elasticsearch.routing;
import org.apache.http.HttpHost;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
/**
* 偏好查询(分片查询方式)
* Created by simoniu
*/
public class EsRoutingDemo {
public static void main(String[] args) throws Exception{
//获取RestClient连接
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
new HttpHost("master",9200,"http"),
new HttpHost("slave1",9200,"http"),
new HttpHost("slave2",9200,"http")));
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("pre");
searchRequest.indices("rout");
//指定分片查询方式
/*
通过偏好查询中的_shard手工指定分片编号在使用的时候不太友好,需要我们单独维护一份数据和分片之间的关系,比较麻烦。
还有一种比较简单常用的方式是在查询的时候设置相同的路由参数,这样就可以快速查询到使用这个路由参数添加的数据了。
底层其实是会计算这个路由参数对应的分片编号,最终到指定的分片中查询数据。*/
//searchRequest.preference("_shards:0");
//指定路由参数
searchRequest.routing("class1");
//我们把routing参数修改一下,改为class2
//searchRequest.routing("class2");
//执行查询操作
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
//获取查询返回的结果
SearchHits hits = searchResponse.getHits();
//获取数据总量
long numHits = hits.getTotalHits().value;
System.out.println("数据总数:"+numHits);
//获取具体内容
SearchHit[] searchHits = hits.getHits();
//迭代解析具体内容
for (SearchHit hit : searchHits) {
String sourceAsString = hit.getSourceAsString();
System.out.println(sourceAsString);
}
//关闭连接
client.close();
}
}
运行结果:
数据总数:8
{"name":"tom","age":18}
{"name":"jack","age":29}
{"name":"jessica","age":18}
{"name":"dave","age":19}
{"name":"lilei","age":18}
{"name":"lili","age":29}
{"name":"simoni","age":28}
{"name":"anthony","age":22}