High Level Client 是基于 Low Level Client 的。官方文档如下:
* .html
* .html
<dependency><groupId>org.elasticsearch.client</groupId><artifactId>transport</artifactId><version>6.5.0</version> </dependency> <dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-core</artifactId><version>2.11.1</version> </dependency> <dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-to-slf4j</artifactId><version>2.11.1</version> </dependency> <dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.25</version> </dependency><dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-client</artifactId><version>6.5.0</version> </dependency> <dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId><version>6.5.0</version> </dependency>
import org.apache.http.HttpHost; import org.elasticsearch.client.RestClient; import org.elasticsearch.client.RestHighLevelClient;/*** Java高级REST客户机在Java低级REST客户机之上工作。它的主要目标是公开特定于API的方法,这些方法接受请求对象作为参数并返回响应对象* 可以同步或异步调用每个API。同步方法返回一个响应对象,而异步方法(其名称以async后缀结尾)需要一个侦听器参数* 一旦接收到响应或错误,侦听器参数(在低层客户机管理的线程池上)将被通知。* Java高级REST客户机依赖于Elasticsearch核心项目。它接受与TransportClient相同的请求参数,并返回相同的响应对象。* Java高级REST客户机需要Java 1.8* 客户机版本与开发客户机的Elasticsearch版本相同* 6.0客户端能够与任意6.X节点通信,6.1客户端能够与6.1、6.2和任意6.X通信*/ public class RestClientFactory {private RestClientFactory(){}private static class Inner{private static final RestClientFactory instance = new RestClientFactory();}public static RestClientFactory getInstance(){return Inner.instance;}public RestHighLevelClient getClient(){RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(//new HttpHost("localhost", 9201, "http"),new HttpHost("localhost", 9200, "http")));return client;}}
HTTP请求
查看所有数据 GET twitter/t_doc/_search
---
# 添加数据[index]/[type]/[id] PUT twitter/t_doc/10 {"user" : "kimchy","post_date" : "2018-12-24T11:32:00","message" : "trying out Elasticsearch" }
结果:
{"_index" : "twitter","_type" : "t_doc","_id" : "10","_version" : 1,"result" : "created","_shards" : {"total" : 2,"successful" : 1,"failed" : 0},"_seq_no" : 0,"_primary_term" : 1 }
Java
public static RestHighLevelClient index() throws IOException {RestHighLevelClient client = Instance().getClient();Map<String, Object> jsonMap = new HashMap<>();jsonMap.put("user", "kimchy");jsonMap.put("postDate", new Date());jsonMap.put("message", "trying out Elasticsearch");IndexRequest indexRequest = new IndexRequest("twitter", "t_doc", "1").source(jsonMap);IndexResponse response = client.index(indexRequest, RequestOptions.DEFAULT);System.out.println(response.status().name());return client;}
结果:
CREATED
还有两种形式添加数据
/*** 方式二:XContentBuilder* @return* @throws IOException*/public static RestHighLevelClient index2() throws IOException {RestHighLevelClient client = Instance().getClient();XContentBuilder builder = jsonBuilder();builder.startObject();{builder.field("user", "kimchy");builder.timeField("postDate", new Date());builder.field("message", "trying out Elasticsearch");}dObject();IndexRequest indexRequest = new IndexRequest("twitter", "t_doc", "2").source(builder);IndexResponse response = client.index(indexRequest, RequestOptions.DEFAULT);System.out.println(response.status().name());return client;}/*** 方式三:Object key-pairs对象键* 同步方法* @return* @throws IOException*/public static RestHighLevelClient index3() throws IOException {RestHighLevelClient client = Instance().getClient();IndexRequest indexRequest = new IndexRequest("twitter", "t_doc", "3").source("user", "kimchy","postDate", new Date(),"message", "trying out Elasticsearch");IndexResponse response = client.index(indexRequest, RequestOptions.DEFAULT); // 同步方式 System.out.println(response.status().name());return client;}
还能异步创建&添加数据
/*** 异步方法* @return* @throws IOException*/public static RestHighLevelClient index4() throws IOException, InterruptedException {ActionListener listener = new ActionListener<IndexResponse>() {@Overridepublic void onResponse(IndexResponse indexResponse) {System.out.println("Async:" + indexResponse.status().name());if (Result() == DocWriteResponse.Result.CREATED) {// Todo} else if (Result() == DocWriteResponse.Result.UPDATED) {// Todo }// 处理成功分片小于总分片的情况ReplicationResponse.ShardInfo shardInfo = ShardInfo();if (Total() != Successful()) {// Todo }}@Overridepublic void onFailure(Exception e) {System.out.println("AsyncFailure:" + e.getMessage());e.printStackTrace();}};RestHighLevelClient client = Instance().getClient();IndexRequest indexRequest = new IndexRequest("twitter", "t_doc", "4").source("user", "kimchy","postDate", new Date(),"message", "trying out Elasticsearch").routing("my_route"); // 指定路由 client.indexAsync(indexRequest, RequestOptions.DEFAULT, listener); // 异步方式Thread.sleep(2000);return client;}
结果:
Async:CREATED
HTTP请求
# 获取数据 GET twitter/t_doc/1 结果: {"_index" : "twitter","_type" : "t_doc","_id" : "1","_version" : 1,"found" : true,"_source" : {"postDate" : "2018-12-24T03:42:22.787Z","message" : "trying out Elasticsearch","user" : "kimchy"} }
可以指定routing
GET twitter/t_doc/4?routing=my_route 结果: {"_index" : "twitter","_type" : "t_doc","_id" : "4","_version" : 1,"_routing" : "my_route","found" : true,"_source" : {"user" : "kimchy","postDate" : "2018-12-24T06:08:45.178Z","message" : "trying out Elasticsearch"} }
可以只要数据信息_source
GET twitter/t_doc/4/_source?routing=my_route 结果: {"user" : "kimchy","postDate" : "2018-12-24T06:08:45.178Z","message" : "trying out Elasticsearch" }
Java
public static RestHighLevelClient getOne() throws IOException {RestHighLevelClient client = Instance().getClient();GetRequest request = new GetRequest("twitter", "t_doc", "4").routing("my_route"); // 指定routing的数据,查询也要指定try {GetResponse response = (request, RequestOptions.DEFAULT);System.out.SourceAsString());} catch (ElasticsearchException e) {// 处理找不到index的异常if(e.status() == RestStatus.NOT_FOUND){// TODO }}return client;}
结果:
{"user":"kimchy","postDate":"2018-12-24T06:08:45.178Z","message":"trying out Elasticsearch"}
异步获取,并且指定包含/排除的字段
/*** 查询-额外参数* 异步获取* @return* @throws IOException*/public static RestHighLevelClient getOneOp() throws IOException, InterruptedException {ActionListener<GetResponse> listener = new ActionListener<GetResponse>() {@Overridepublic void onResponse(GetResponse documentFields) {System.out.SourceAsString());}@Overridepublic void onFailure(Exception e) {System.out.println("Error:" + e.getMessage());e.printStackTrace();}};RestHighLevelClient client = Instance().getClient();GetRequest request = new GetRequest("twitter", "t_doc", "1");String[] includes = new String[]{"message", "*Date"}; // 包含的字段String[] excludes = Strings.EMPTY_ARRAY; // 排除的字段FetchSourceContext fetchSourceContext =new FetchSourceContext(true, includes, excludes);request.fetchSourceContext(fetchSourceContext);Async(request, RequestOptions.DEFAULT, listener);Thread.sleep(2000);return client;}
结果:
{"postDate":"2018-12-24T03:42:22.787Z","message":"trying out Elasticsearch"}
到这里也应该知道,Rest API 对每个操作提供了同步/异步的方法。
Java
/*** 检查是否存在* @return* @throws IOException*/public static RestHighLevelClient exist() throws IOException {RestHighLevelClient client = Instance().getClient();GetRequest request = new GetRequest("twitter", "t_doc", "1");request.storedFields("_none_"); // 禁用获取存储字段request.fetchSourceContext(FetchSourceContext.DO_NOT_FETCH_SOURCE); // 禁用抓取_sourceboolean exists = ists(request, RequestOptions.DEFAULT);System.out.println(exists);return client;}
结果:
true
HTTP请求
DELETE twitter/t_doc/1 结果: {"_index" : "twitter","_type" : "t_doc","_id" : "1","_version" : 2,"result" : "deleted","_shards" : {"total" : 2,"successful" : 1,"failed" : 0},"_seq_no" : 1,"_primary_term" : 1 }
Java
/*** 删除也可以异步、也可以捕获异常,成功删除的分片数量,版本冲突* @return* @throws IOException*/public static RestHighLevelClient deleteOne() throws IOException {RestHighLevelClient client = Instance().getClient();DeleteRequest request = new DeleteRequest("twitter", "t_doc", "1");DeleteResponse response = client.delete(request, RequestOptions.DEFAULT);System.out.println(response.status().name());// 处理找不到的情况if (Result() == DocWriteResponse.Result.NOT_FOUND) {// TODO }return client;}
结果:
NOT_FOUND
我这里有4条测试数据
{"user":"Tom","flag":"1"} {"user":"foo","flag":"2"} {"user":"bar","flag":"2"} {"user":"baz","flag":"2"}
HTTP 请求
# 删除flag=2的数据 POST twitter/_delete_by_query?conflicts=proceed {"query": { "match": {"flag": "2"}} } 结果: {"took" : 183,"timed_out" : false,"total" : 3,"deleted" : 3,"batches" : 1,"version_conflicts" : 0,"noops" : 0,"retries" : {"bulk" : 0,"search" : 0},"throttled_millis" : 0,"requests_per_second" : -1.0,"throttled_until_millis" : 0,"failures" : [ ] }
--扩展
# 清空索引全部数据 POST /[索引名]/_delete_by_query {"query": { "match_all": {}} }
Java
/*** 根据查询条件删除* @return* @throws IOException*/public static RestHighLevelClient deleteByQuery() throws IOException {RestHighLevelClient client = Instance().getClient();DeleteByQueryRequest request = new DeleteByQueryRequest("twitter");request.setConflicts("proceed"); // 发生冲突即略过request.setQuery(QueryBuilders.matchQuery("flag","2"));BulkByScrollResponse bulkResponse = client.deleteByQuery(request, RequestOptions.DEFAULT);TimeValue timeTaken = Took();boolean timedOut = bulkResponse.isTimedOut();long totalDocs = Total();long updatedDocs = Updated();long deletedDocs = Deleted();long batches = Batches();long noops = Noops();long versionConflicts = VersionConflicts();System.out.println("花费时间:" + timeTaken + ",是否超时:" + timedOut + ",总文档数:" + totalDocs + ",更新数:" +updatedDocs + ",删除数:" + deletedDocs + ",批量次数:" + batches + ",跳过数:" + noops + ",冲突数:" + versionConflicts);List<ScrollableHitSource.SearchFailure> searchFailures = SearchFailures(); // 搜索期间的故障searchFailures.forEach(e -> {println("Cause:" + e.getReason().getMessage() + "Index:" + e.getIndex() + ",NodeId:" + e.getNodeId() + ",ShardId:" + e.getShardId());});List<BulkItemResponse.Failure> bulkFailures = BulkFailures(); // 批量索引期间的故障bulkFailures.forEach(e -> {println("Cause:" + e.getCause().getMessage() + "Index:" + e.getIndex() + ",Type:" + e.getType() + ",Id:" + e.getId());});return client;}
结果:
花费时间:97ms,是否超时:false,总文档数:3,更新数:0,删除数:3,批量次数:1,跳过数:0,冲突数:0
我有一条测试数据
{"user":"Tom","flag":"1"}
HTTP 请求
# 通过脚本更新 POST twitter/t_doc/1/_update {"script" : {"source": "ctx._source.msg = params.msg","lang": "painless","params" : {"msg" : "達に携帯で連絡取ろうと思ったら 電池が切れてて動かない"}} } # 通过文档更新 POST twitter/t_doc/1/_update {"doc" : {"user" : "new_name"} }
upserts
# upserts(如果文档不存在,则把upsert里面的内容作为文档插入) POST twitter/t_doc/2/_update {"script" : {"source": "ctx._unter += unt","lang": "painless","params" : {"count" : 4}},"upsert" : {"counter" : 1} } 结果【创建新文档】: {"_index" : "twitter","_type" : "t_doc","_id" : "2","_version" : 1,"result" : "created","_shards" : {"total" : 2,"successful" : 1,"failed" : 0},"_seq_no" : 1,"_primary_term" : 1 }
如果你再执行的话就是更新了
结果【更新文档】: {"_index" : "twitter","_type" : "t_doc","_id" : "2","_version" : 2,"result" : "updated","_shards" : {"total" : 2,"successful" : 1,"failed" : 0},"_seq_no" : 2,"_primary_term" : 1 } 查询: GET twitter/t_doc/2 结果: {"_index" : "twitter","_type" : "t_doc","_id" : "2","_version" : 2,"found" : true,"_source" : {"counter" : 5} }
不用脚本而用文档更新
# 如果文档不存在,则将doc内容作为新文档插入(因为"doc_as_upsert" : true) POST twitter/t_doc/3/_update {"doc" : {"name" : "new_name"},"doc_as_upsert" : true } 结果: {"_index" : "twitter","_type" : "t_doc","_id" : "3","_version" : 1,"result" : "created","_shards" : {"total" : 2,"successful" : 1,"failed" : 0},"_seq_no" : 5,"_primary_term" : 1 } 查询: GET twitter/t_doc/3 结果: {"_index" : "twitter","_type" : "t_doc","_id" : "3","_version" : 1,"found" : true,"_source" : {"name" : "new_name"} }
Java
/*** 通过脚本更新,可以添加字段* @return*/public static RestHighLevelClient updateOne() throws IOException {RestHighLevelClient client = Instance().getClient();UpdateRequest request = new UpdateRequest("twitter", "t_doc", "1");Map<String, Object> parameters = singletonMap("msg", "達に携帯で連絡取ろうと思ったら 電池が切れてて動かない");Script inline = new Script(ScriptType.INLINE, "painless","ctx._source.msg = params.msg", parameters);request.script(inline);UpdateResponse update = client.update(request, RequestOptions.DEFAULT);System.out.println(update.status().name());return client;}
输出:OK
GET twitter/t_doc/1 结果: {"_index" : "twitter","_type" : "t_doc","_id" : "1","_version" : 4,"found" : true,"_source" : {"user" : "Tom","flag" : "1","msg" : "達に携帯で連絡取ろうと思ったら 電池が切れてて動かない"} }
还可以通过XContentBuilder
/*** 通过XContentBuilder更新* @return* @throws IOException*/public static RestHighLevelClient updateOne2() throws IOException {RestHighLevelClient client = Instance().getClient();XContentBuilder builder = jsonBuilder().startObject().startObject("animal").field("cat", "阿猫").field("dog", "阿狗").endObject().endObject();UpdateRequest request = new UpdateRequest("twitter", "t_doc", "1").doc(builder);UpdateResponse update = client.update(request, RequestOptions.DEFAULT);System.out.println(update.status().name());return client;}
输出:OK
GET twitter/t_doc/1 结果: {"_index" : "twitter","_type" : "t_doc","_id" : "1","_version" : 5,"found" : true,"_source" : {"user" : "Tom","flag" : "1","msg" : "達に携帯で連絡取ろうと思ったら 電池が切れてて動かない","animal" : {"cat" : "阿猫","dog" : "阿狗"}} }
还可以通过Map
/*** 通过jsonMap更新* @return* @throws IOException*/public static RestHighLevelClient updateOne3() throws IOException {RestHighLevelClient client = Instance().getClient();Map<String, Object> jsonMap = new HashMap<>();jsonMap.put("updateUser", "Jack Ma");UpdateRequest request = new UpdateRequest("posts", "doc", "1").doc(jsonMap);UpdateResponse update = client.update(request, RequestOptions.DEFAULT);System.out.println(update.status().name());return client;}
输出:OK
GET twitter/t_doc/1 结果: {"_index" : "twitter","_type" : "t_doc","_id" : "1","_version" : 6,"found" : true,"_source" : {"user" : "Tom","flag" : "1","msg" : "達に携帯で連絡取ろうと思ったら 電池が切れてて動かない","animal" : {"cat" : "阿猫","dog" : "阿狗"},"updateUser" : "Jack Ma"} }
还可以通过 key-pairs
/*** 通过 key-pairs 更新* @return* @throws IOException*/public static RestHighLevelClient updateOne4() throws IOException {RestHighLevelClient client = Instance().getClient();UpdateRequest request = new UpdateRequest("twitter", "t_doc", "1").doc("favorite","二狗","hate","no Money");UpdateResponse update = client.update(request, RequestOptions.DEFAULT);System.out.println(update.status().name());return client;}
输出:OK
GET twitter/t_doc/1 结果: {"_index" : "twitter","_type" : "t_doc","_id" : "1","_version" : 7,"found" : true,"_source" : {"user" : "Tom","flag" : "1","msg" : "達に携帯で連絡取ろうと思ったら 電池が切れてて動かない","animal" : {"cat" : "阿猫","dog" : "阿狗"},"updateUser" : "Jack Ma","hate" : "no Money","favorite" : "二狗"} }
upserts
/*** 存在即更新【输出:OK】* OK* {"C":"Carambola","A":"Apple","B":"Banana"}* 不存在则创建【输出:CREATED】* CREATED* {"C":"Carambola"}* 开启scriptedUpsert【在文档不存在情况下输出:CREATED】* {"A" : "Apple","B" : "Banana","C" : "Carambola"}* @return* @throws IOException*/public static RestHighLevelClient upserts() throws IOException {RestHighLevelClient client = Instance().getClient();UpdateRequest request = new UpdateRequest("twitter", "t_doc", "7").script(new Script(ScriptType.INLINE,"painless","ctx._source.A='Apple';ctx._source.B='Banana'",Collections.EMPTY_MAP))// 如果文档不存在,使用upsert方法定义一些内容,这些内容将作为新文档插入 .upsert(jsonBuilder().startObject().field("C","Carambola").endObject());request.timeout(TimeValue.timeValueSeconds(2)); // 2秒超时//request.scriptedUpsert(true); // 无论文档是否存在,脚本都必须运行UpdateResponse update = client.update(request, RequestOptions.DEFAULT);System.out.println(update.status().name());return client;}
--
/*** 存在即更新* OK* {"C" : "Carambola","A" : "Apple","B" : "Banana","D" : "Dew"}* 不存在则创建* CREATED* {"C" : "Carambola"}* 开启docAsUpsert【在文档不存在情况下输出:CREATED】* {"A" : "Apple","B" : "Banana","D" : "Dew"}* @return* @throws IOException*/public static RestHighLevelClient upserts2() throws IOException {RestHighLevelClient client = Instance().getClient();UpdateRequest request = new UpdateRequest("twitter", "t_doc", "8").doc(jsonBuilder().startObject().field("A","Apple").field("B","Banana").field("D","Dew").endObject())// 如果指定docAsUpsert(true),会忽略upsert方法 .upsert(jsonBuilder().startObject().field("C","Carambola").endObject());//request.docAsUpsert(true); // 如果部分文档尚不存在,则必须将doc用作upsert文档request.timeout(TimeValue.timeValueSeconds(2)); // 2秒超时try {UpdateResponse update = client.update(request, RequestOptions.DEFAULT);System.out.println(update.status().name());} catch (ElasticsearchException e) {if (e.status() == RestStatus.NOT_FOUND) {// TODO }}return client;}
HTTP请求
# 不更改源数据的前提下更新文档 POST twitter/_update_by_query?conflicts=proceed 结果: {"took" : 186,"timed_out" : false,"total" : 9,"updated" : 9,"deleted" : 0,"batches" : 1,"version_conflicts" : 0,"noops" : 0,"retries" : {"bulk" : 0,"search" : 0},"throttled_millis" : 0,"requests_per_second" : -1.0,"throttled_until_millis" : 0,"failures" : [ ] }
--
我们有数据:
{"_index" : "twitter","_type" : "t_doc","_id" : "9","_version" : 3,"found" : true,"_source" : {"flag" : "2","user" : "foo"} }
# 通过脚本更新 POST twitter/_update_by_query?conflicts=proceed {"script": {"source": "ctx._source.flag++","lang": "painless"},"query": {"term": {"user": "foo"}} } 结果: {"took" : 102,"timed_out" : false,"total" : 1,"updated" : 1,"deleted" : 0,"batches" : 1,"version_conflicts" : 0,"noops" : 0,"retries" : {"bulk" : 0,"search" : 0},"throttled_millis" : 0,"requests_per_second" : -1.0,"throttled_until_millis" : 0,"failures" : [ ] }
Java
/*** 根据查询条件更新* @return*/public static RestHighLevelClient updateByQuery() throws IOException {RestHighLevelClient client = Instance().getClient();UpdateByQueryRequest request = new UpdateByQueryRequest("twitter");request.setConflicts("proceed");request.setQuery(QueryBuilders.matchAllQuery()).setBatchSize(50) // 批处理大小.setSize(100) // 限制处理文档的数量.setScript(new Script(ScriptType.INLINE, "painless","if (ctx._source.flag == '2') {ctx._Msg = '小林さんちのメイドラゴン';}", // 增加一个字段extMsg ptyMap()));BulkByScrollResponse bulkResponse = client.updateByQuery(request, RequestOptions.DEFAULT);TimeValue timeTaken = Took();boolean timedOut = bulkResponse.isTimedOut();long totalDocs = Total();long updatedDocs = Updated();long deletedDocs = Deleted();long batches = Batches();long noops = Noops();long versionConflicts = VersionConflicts();System.out.println("花费时间:" + timeTaken + ",是否超时:" + timedOut + ",总文档数:" + totalDocs + ",更新数:" +updatedDocs + ",删除数:" + deletedDocs + ",批量次数:" + batches + ",跳过数:" + noops + ",冲突数:" + versionConflicts);List<ScrollableHitSource.SearchFailure> searchFailures = SearchFailures(); // 搜索期间的故障searchFailures.forEach(e -> {println("Cause:" + e.getReason().getMessage() + "Index:" + e.getIndex() + ",NodeId:" + e.getNodeId() + ",ShardId:" + e.getShardId());});List<BulkItemResponse.Failure> bulkFailures = BulkFailures(); // 批量索引期间的故障bulkFailures.forEach(e -> {println("Cause:" + e.getCause().getMessage() + "Index:" + e.getIndex() + ",Type:" + e.getType() + ",Id:" + e.getId());});return client;}
结果:【之所以更新了全部文档,是因为matchAllQuery】
花费时间:218ms,是否超时:false,总文档数:9,更新数:9,删除数:0,批量次数:1,跳过数:0,冲突数:0
# 查询flag=2的文档 GET /twitter/_search {"query": { "match": {"flag": "2"}} } 结果: {"took" : 0,"timed_out" : false,"_shards" : {"total" : 5,"successful" : 5,"skipped" : 0,"failed" : 0},"hits" : {"total" : 2,"max_score" : 0.6931472,"hits" : [{"_index" : "twitter","_type" : "t_doc","_id" : "10","_score" : 0.6931472,"_source" : {"flag" : "2","extMsg" : "小林さんちのメイドラゴン","user" : "bar"}},{"_index" : "twitter","_type" : "t_doc","_id" : "11","_score" : 0.2876821,"_source" : {"flag" : "2","extMsg" : "小林さんちのメイドラゴン","user" : "baz"}}]} }
HTTP请求
# 批量处理(允许Add,Delete,Update操作)如果包含routing要加上 POST _bulk { "delete" : { "_index" : "twitter", "_type" : "t_doc", "_id" : "9" } } { "update" : { "_index" : "twitter", "_type" : "t_doc", "_id" : "4","routing":"my_route" } } { "doc" : {"user":"new_user"} } { "index" : { "_index" : "twitter", "_type" : "t_doc", "_id" : "21" }} { "user":"Tom","flag":"1" } { "index" : { "_index" : "twitter", "_type" : "t_doc", "_id" : "22" }} { "user":"Tony","flag":"1" } { "index" : { "_index" : "twitter", "_type" : "t_doc", "_id" : "23" }} { "user":"Mary","flag":"1" } { "index" : { "_index" : "twitter", "_type" : "t_doc", "_id" : "24" }} { "user":"Jerry","flag":"1" }
Java
/*** 批量添加* @return*/public static RestHighLevelClient bulkAdd() throws IOException {RestHighLevelClient client = Instance().getClient();BulkRequest request = new BulkRequest();request.add(new IndexRequest("twitter", "t_doc", "25").source(XContentType.JSON,"user", "Tom","flag","1"));request.add(new IndexRequest("twitter", "t_doc", "26").source(XContentType.JSON,"user", "foo","flag","2"));request.add(new IndexRequest("twitter", "t_doc", "27").source(XContentType.JSON,"user", "bar","flag","2"));request.add(new IndexRequest("twitter", "t_doc", "28").source(XContentType.JSON,"user", "baz","flag","2"));BulkResponse bulk = client.bulk(request, RequestOptions.DEFAULT);System.out.println("Status:" + bulk.status().name() + ",hasFailures:" + bulk.hasFailures());// 下面是multiGetMultiGetRequest multiGetRequest = new MultiGetRequest().add(new MultiGetRequest.Item("twitter", "t_doc", "25")).add(new MultiGetRequest.Item("twitter", "t_doc", "26")).add(new MultiGetRequest.Item("twitter", "t_doc", "27")).add(new MultiGetRequest.Item("twitter", "t_doc", "28"));MultiGetResponse response = (multiGetRequest, RequestOptions.DEFAULT);MultiGetItemResponse[] itemResponses = Responses();for(MultiGetItemResponse r : itemResponses){System.out.Response().getSourceAsString());}return client;}
输出:
Status:OK,hasFailures:false {"user":"Tom","flag":"1"} {"user":"foo","flag":"2"} {"user":"bar","flag":"2"} {"user":"baz","flag":"2"}
也可以批量更新
/*** 批量更新* @return*/public static RestHighLevelClient bulkUpdate() throws IOException {RestHighLevelClient client = Instance().getClient();BulkRequest request = new BulkRequest();// 更新request.add(new UpdateRequest("twitter", "t_doc", "27").doc(XContentType.JSON,"field", "foo","color", "red","size", "100"));// 添加request.add(new IndexRequest("twitter", "t_doc", "29").source(XContentType.JSON,"field", "bar","color", "blue","size", "200"));// 删除request.add(new DeleteRequest("twitter", "t_doc", "28"));BulkResponse bulk = client.bulk(request, RequestOptions.DEFAULT);System.out.println("Status:" + bulk.status().name() + ",hasFailures:" + bulk.hasFailures());// 针对不同类型进行处理for (BulkItemResponse bulkItemResponse : bulk) {DocWriteResponse itemResponse = Response();if (OpType() == DocWriteRequest.OpType.INDEX|| OpType() == DocWriteRequest.OpType.CREATE) {IndexResponse indexResponse = (IndexResponse) itemResponse;System.out.println(indexResponse.status().name());} else if (OpType() == DocWriteRequest.OpType.UPDATE) {UpdateResponse updateResponse = (UpdateResponse) itemResponse;System.out.println(updateResponse.status().name());} else if (OpType() == DocWriteRequest.OpType.DELETE) {DeleteResponse deleteResponse = (DeleteResponse) itemResponse;System.out.println(deleteResponse.status().name());}}String[] includes = Strings.EMPTY_ARRAY;String[] excludes = new String[] {"flag"};// 包含/排除的字段FetchSourceContext fetchSourceContext =new FetchSourceContext(true, includes, excludes);MultiGetRequest multiGetRequest = new MultiGetRequest().add(new MultiGetRequest.Item("twitter", "t_doc", "29").fetchSourceContext(fetchSourceContext)).add(new MultiGetRequest.Item("twitter", "t_doc", "28").fetchSourceContext(fetchSourceContext)).add(new MultiGetRequest.Item("twitter", "t_doc", "27").fetchSourceContext(fetchSourceContext));MultiGetResponse response = (multiGetRequest, RequestOptions.DEFAULT);MultiGetItemResponse[] itemResponses = Responses();for(MultiGetItemResponse r : itemResponses){System.out.Response().getSourceAsString());}return client;}
输出:
Status:OK,hasFailures:false OK CREATED OK {"field":"bar","color":"blue","size":"200"} null {"field":"foo","color":"red","size":"100","user":"bar"}
bulkProcessor就比较厉害了
/*** BulkProcessor通过提供一个实用程序类来简化Bulk API的使用,它允许索引/更新/删除操作在添加到处理器时透明地执行。* 为了执行请求,BulkProcessor需要以下组件:* RestHighLevelClient* 此客户端用于执行BulkRequest和检索BulkResponse* BulkProcessor.Listener* 在每个BulkRequest执行之前和之后,或者在BulkRequest失败时,都会调用这个侦听器* BulkProcessor.builder方法可用于构建新的BulkProcessor:* @return*/public static RestHighLevelClient bulkProcessor() throws InterruptedException {RestHighLevelClient client = Instance().getClient();BulkProcessor.Listener listener = new BulkProcessor.Listener() {@Overridepublic void beforeBulk(long executionId, BulkRequest request) {int numberOfActions = request.numberOfActions();System.out.println("请求数量:" + numberOfActions);}@Overridepublic void afterBulk(long executionId, BulkRequest request, BulkResponse response) {if (response.hasFailures()) {System.out.println("Bulk Failures,ID:" + executionId + ",Status:" + response.status().name());for (BulkItemResponse bulkItemResponse : response) {if (bulkItemResponse.isFailed()) {BulkItemResponse.Failure failure = Failure();Cause().getMessage()); }}} else {System.out.println("Bulk "+ executionId +" Complete in" + Took().getMillis() + "s");}}@Overridepublic void afterBulk(long executionId, BulkRequest request, Throwable failure) {System.out.println("Failed to execute bulk:" + failure);}};BiConsumer<BulkRequest, ActionListener<BulkResponse>> bulkConsumer =(request, bulkListener) -> client.bulkAsync(request, RequestOptions.DEFAULT, bulkListener);BulkProcessor bulkProcessor = BulkProcessor.builder(bulkConsumer, listener).setBulkActions(500) // 请求(Index,Update,Delete)的数量达到500,就刷新一次bulk request【默认1000】 // .setBulkSize(new ByteSizeValue(1L, ByteSizeUnit.MB)) // 累计请求所占的空间达到1M,就刷新一次bulk request【默认5M】.setConcurrentRequests(0) // 设置允许执行的并发请求数量(默认为1,使用0只允许执行单个请求) // .setFlushInterval(TimeValue.timeValueSeconds(10L)) // 每隔一段时间刷新一次【默认未设置】 .stantBackoff(TimeValue.timeValueSeconds(1L), 3))// 设置一个初始等待1秒并重试3次的Backoff策略 .build();for(int i = 1; i <= 2000; i++){bulkProcessor.add(new IndexRequest("books", "java", ""+i).source(XContentType.JSON,"title","title_"+i,"user","user_"+i));}bulkProcessor.flush();Thread.sleep(2000);bulkProcessor.close();return client;}
输出:【警告可忽略,因为默认分片数量在7.0.0版本会改变,这里提醒一下用户。也就是说,最好先去建立索引(设置好参数),再来添加数据】
请求数量:500 十二月 25, 2018 11:24:06 上午 org.elasticsearch.client.RestClient logResponse 警告: request [POST localhost:9200/_bulk?timeout=1m] returned 1 warnings: [299 Elasticsearch-6.5.0-816e6f6 "the default number of shards will change from [5] to [1] in 7.0.0; if you wish to continue using the default of [5] shards, you must manage this on the create index request or with an index template" "Tue, 25 Dec 2018 03:24:04 GMT"] Bulk 1 Complete in2044s 请求数量:500 Bulk 2 Complete in333s 请求数量:500 Bulk 3 Complete in235s 请求数量:500 Bulk 4 Complete in244s
查看:
GET books/_search 结果: {"took" : 18,"timed_out" : false,"_shards" : {"total" : 5,"successful" : 5,"skipped" : 0,"failed" : 0},"hits" : {"total" : 2000,"max_score" : 1.0,"hits" : [{"_index" : "books","_type" : "java","_id" : "14","_score" : 1.0,"_source" : {"title" : "title_14","user" : "user_14"}},....]} }
HTTP 请求
GET /_mget {"docs" : [{"_index" : "books","_type" : "java","_id" : "1"},{"_index" : "twitter","_type" : "t_doc","_id" : "1"}] } 结果: {"docs" : [{"_index" : "books","_type" : "java","_id" : "1","_version" : 1,"found" : true,"_source" : {"title" : "title_1","user" : "user_1"}},{"_index" : "twitter","_type" : "t_doc","_id" : "1","_version" : 13,"found" : true,"_source" : {"msg" : "達に携帯で連絡取ろうと思ったら 電池が切れてて動かない","flag" : "1","user" : "new_name"}}] }
GET /twitter/t_doc/_mget {"docs" : [{"_id" : "1"},{"_id" : "2"}] } GET /twitter/t_doc/_mget {"ids" : ["1", "2"] } # 两个方式效果一样 结果: {"docs" : [{"_index" : "twitter","_type" : "t_doc","_id" : "1","_version" : 13,"found" : true,"_source" : {"msg" : "達に携帯で連絡取ろうと思ったら 電池が切れてて動かない","flag" : "1","user" : "new_name"}},{"_index" : "twitter","_type" : "t_doc","_id" : "2","_version" : 5,"found" : true,"_source" : {"counter" : 5,"user" : "new_user"}}] }
Java代码在bulk里面有体现,这里就不赘述了。
Reindex不尝试设置目标索引。它不复制源索引的设置。您应该在运行_reindex操作之前设置目标索引,包括设置映射、碎片计数、副本等。
# 复制源索引twitter到目标索引new_twitter POST _reindex {"source": {"index": "twitter"},"dest": {"index": "new_twitter"} } 结果: {"took" : 1626,"timed_out" : false,"total" : 16,"updated" : 0,"created" : 16,"deleted" : 0,"batches" : 1,"version_conflicts" : 0,"noops" : 0,"retries" : {"bulk" : 0,"search" : 0},"throttled_millis" : 0,"requests_per_second" : -1.0,"throttled_until_millis" : 0,"failures" : [ ] } # 查询 GET /new_twitter/_search 结果: {"took" : 9,"timed_out" : false,"_shards" : {"total" : 5,"successful" : 5,"skipped" : 0,"failed" : 0},"hits" : {"total" : 16,"max_score" : 1.0,"hits" : [{"_index" : "new_twitter","_type" : "t_doc","_id" : "22","_score" : 1.0,"_source" : {"user" : "Tony","flag" : "1"}},...]} }
为了避免出现冲突导致进程停止,指定:conflicts:proceed
POST _reindex {"conflicts": "proceed","source": {"index": "twitter"},"dest": {"index": "new_twitter","op_type": "create"} }
还可以查询出指定的内容,然后送进目标索引
POST _reindex {"source": {"index": "twitter","type": "t_doc","query": {"term": {"user": "kimchy"}}},"dest": {"index": "new_twitter"} }
和可以合并多个索引到目标索引
#合并两个索引,跳过冲突【conflicts】,只转移10000条数据【size】 POST _reindex {"conflicts": "proceed","size": 10000,"source": {"index": ["twitter", "new_twitter"],"type": ["t_doc", "post"]},"dest": {"index": "all_together","type": "all_doc"} }
还可以使用脚本、从远程服务器reindex、修改目标字段名称,请参考官方文档
Java
/*** reIndex可用于将文档从一个或多个索引复制到目标索引* DocWriteRequest.OpType.CREATE 跳过已有的文档* DocWriteRequest.OpType.INDEX 已有相同id的会被覆盖* @return*/public static RestHighLevelClient reIndex() throws IOException {RestHighLevelClient client = Instance().getClient();ReindexRequest reindexRequest = new ReindexRequest().setSourceIndices("twitter","new_twitter").setDestIndex("all_together").setDestOpType(DocWriteRequest.Lowercase()).setDestDocType("all_doc") // .setSize(10) // copy的文档数 // .setScript(new Script(ScriptType.INLINE, "painless", // "if (ctx._source.user == 'kimchy') {ctx._source.likes++;}", // ptyMap())) // 脚本.setSourceBatchSize(500); // 默认批量为1000,你可以自己设置批次获取的数量reindexRequest.setConflicts("proceed"); // 默认情况下,版本冲突会中止_reindex进程(abort)BulkByScrollResponse bulkResponse = index(reindexRequest, RequestOptions.DEFAULT);TimeValue timeTaken = Took();boolean timedOut = bulkResponse.isTimedOut();long totalDocs = Total();long updatedDocs = Updated();long createdDocs = Created();long deletedDocs = Deleted();long batches = Batches();long noops = Noops(); // 跳过的文档数long versionConflicts = VersionConflicts(); // 版本冲突的数量long bulkRetries = BulkRetries(); // bulk重试次数long searchRetries = SearchRetries(); // 搜索重试次数System.out.println("花费时间:" + timeTaken + ",是否超时:" + timedOut + ",总文档数:" + totalDocs + ",更新数:" +updatedDocs + ",创建数:" + createdDocs + ",删除数:" + deletedDocs + ",批量次数:" + batches + ",跳过数:" +noops + ",冲突数:" + versionConflicts + ",bulk重试次数:" + bulkRetries + ",搜索重试次数:" + searchRetries);List<ScrollableHitSource.SearchFailure> searchFailures = SearchFailures(); // 搜索期间的故障searchFailures.forEach(e -> {println("Cause:" + e.getReason().getMessage() + "Index:" + e.getIndex() + ",NodeId:" + e.getNodeId() + ",ShardId:" + e.getShardId());});List<BulkItemResponse.Failure> bulkFailures = BulkFailures(); // 批量索引期间的故障bulkFailures.forEach(e -> {println("Cause:" + e.getCause().getMessage() + "Index:" + e.getIndex() + ",Type:" + e.getType() + ",Id:" + e.getId());});return client;}
因为这两个索引内容一样,所以会出现 更新数:16,创建数:16
花费时间:1.6s,是否超时:false,总文档数:32,更新数:16,创建数:16,删除数:0,批量次数:1,跳过数:0,冲突数:0,bulk重试次数:0,搜索重试次数:0
查看目标索引(总文档数16)
GET /all_together/_search 结果: {"took" : 4,"timed_out" : false,"_shards" : {"total" : 5,"successful" : 5,"skipped" : 0,"failed" : 0},"hits" : {"total" : 16,"max_score" : 1.0,"hits" : [{"_index" : "all_together","_type" : "all_doc","_id" : "22","_score" : 1.0,"_source" : {"user" : "Tony","flag" : "1"}},...]} }
--
HTTP请求
RequestBodySearch 示例
# sort--mode:min、max、sum、avg、median # sort--order:asc、desc # 过滤_source:如果要禁用,"_source": false # Doc格式化:.html # 高亮参数:写在外面是全局的,写在field里面是局部的 GET /_search {"query" : {"term" : { "user" : "Tony" }},"_source": [ "obj1.*", "obj2.*" ],"from" : 0, "size" : 10,"sort" : [{"price" : {"order" : "asc", "mode" : "avg"}}],"script_fields" : {"my_field1" : {"script" : {"lang": "painless","source": "doc['flag'].value * params.factor","params" : {"factor" : 2.0}}}},"docvalue_fields" : [{"field": "postDate", "format": "yyyy-MM-dd" }],"highlight" : {"order" : "score","pre_tags" : ["<tag1>"],"post_tags" : ["</tag1>"],"fields" : {"_all" : {},"message" : {"fragment_size" : 150, "number_of_fragments" : 3}}} }
QueryDSL
**Match 与 Match Phrase【这里使用了ik分词器】
# 准备测试数据 PUT test {"settings" : {"number_of_shards" : 1,"number_of_replicas" : 1},"mappings" : {"msg" : {"properties" : {"message" : { "type" : "text","analyzer": "ik_max_word" }}}} } PUT test/msg/100 {"message" : "她过山车一般的跌宕人生,成了 2018 年我听过的最精彩、也最让人感叹唏嘘的真人真事。"} PUT test/msg/101 {"message" : "她就是我们今天的主人公,伊丽莎白·福尔摩斯(Elizabeth Holmes)。"} # match query GET /_search {"query": {"match" : {"message" : {"query" : "今天的主人公","analyzer" : "ik_max_word"}}} }# Match Phrase Query 短语查询 GET /_search {"query": {"match_phrase" : {"message" : {"query" : "今天的主人公","analyzer" : "ik_max_word"}}} }
执行match的结果:
执行match phrase的结果
分词器:
POST _analyze {"analyzer": "ik_max_word","text": "今天的主人公" } --- {"tokens" : [{"token" : "今天","start_offset" : 0,"end_offset" : 2,"type" : "CN_WORD","position" : 0},{"token" : "的","start_offset" : 2,"end_offset" : 3,"type" : "CN_CHAR","position" : 1},{"token" : "主人公","start_offset" : 3,"end_offset" : 6,"type" : "CN_WORD","position" : 2},{"token" : "主人","start_offset" : 3,"end_offset" : 5,"type" : "CN_WORD","position" : 3},{"token" : "公","start_offset" : 5,"end_offset" : 6,"type" : "CN_CHAR","position" : 4}] }
结论:match会查出包含所有token的结果,而matchPhrase则只会查询“今天的主人公”这一个词组。
**Match Phrase Prefix Query,短语前缀查询,顾名思义:以查询关键字为前缀的查询
# Match Phrase Prefix Query 短语前缀查询 GET /_search {"query": {"match_phrase_prefix" : {"message" : {"query" : "她就是","analyzer" : "ik_max_word"}}} } --- {"took" : 9,"timed_out" : false,"_shards" : {"total" : 28,"successful" : 28,"skipped" : 0,"failed" : 0},"hits" : {"total" : 1,"max_score" : 3.2103658,"hits" : [{"_index" : "test","_type" : "msg","_id" : "101","_score" : 3.2103658,"_source" : {"message" : "她就是我们今天的主人公,伊丽莎白·福尔摩斯(Elizabeth Holmes)。"}}]} }
**Query String Query
# 字符串查询 如果多个字段:"fields" : ["content", "name"] 代替default_field GET /_search {"query": {"query_string" : {"default_field" : "message","query" : "(过山车) OR (伊丽莎白)" }} } --- {"took" : 5,"timed_out" : false,"_shards" : {"total" : 28,"successful" : 28,"skipped" : 0,"failed" : 0},"hits" : {"total" : 2,"max_score" : 0.80259144,"hits" : [{"_index" : "test","_type" : "msg","_id" : "101","_score" : 0.80259144,"_source" : {"message" : "她就是我们今天的主人公,伊丽莎白·福尔摩斯(Elizabeth Holmes)。"}},{"_index" : "test","_type" : "msg","_id" : "100","_score" : 0.6099695,"_source" : {"message" : "她过山车一般的跌宕人生,成了 2018 年我听过的最精彩、也最让人感叹唏嘘的真人真事。"}}]} }
以下查询的字段类型都为keyword,适合精确查询
**TermQuery
# Term Query 适合关键字的查询,字段类型为keyword GET /_search {"query": {"term": {"exact_value": "Quick Foxes!" }} }
**Terms Query
# Terms Query 对同一个字段匹配多个关键字 GET /_search {"query": {"terms" : { "user" : ["kimchy", "elasticsearch"]}} }
**Range Query
# Range Query 范围查询【gt:大于,gte:大于等于,lt:小于,lte:小于等于】 GET _search {"query": {"range" : {"age" : {"gte" : 10,"lte" : 20,"boost" : 2.0}}} } # Range Query 日期【y-年,M-月,w-周,d-日,h-小时,H-小时,m-分钟,s-秒。+1h:+1小时,-1d:-1天,/d:四舍五入到最近的日期,now:当前时间】比如:now = 2018-12-23 17:17:00 now/d = 2018-12-24 00:00:00 GET _search {"query": {"range" : {"date" : {"gte" : "now-1d/d","lt" : "now/d"}}} } GET _search {"query": {"range" : {"birthday" : {"gte": "01/01/2012","lte": "2013","format": "dd/MM/yyyy||yyyy"}}} }
**Exists Query
# Exist Query 返回在原始字段 message 中至少有一个非空值的文档 GET /_search {"query": {"exists" : { "field" : "message" }} }
**Prefix Query
# Prefix Query 前缀查询 GET /_search { "query": {"prefix" : { "user" : "ki" }} }
**Wildcard Query
# Wildcard Query 不建议以通配符开头,因为那样性能最低 GET /_search {"query": {"wildcard" : { "user" : "ki*y" }} }
**Regexp Query
# Regexp Query 正则查询,你可以使用任何正则表达式,同样不建议以通配符开头 GET /_search {"query": {"regexp":{"name.first": "s.*y"}} }
**Fuzzy Query
# Fuzzy Query 模糊查询【与SQL的模糊查询不一样,更多信息请自行查阅资料】 GET /_search {"query": {"fuzzy" : { "user" : "ki" }} }
**Type Query
# Type Query 查询type下的所有文档 GET /_search {"query": {"type" : {"value" : "t_doc"}} }
**Ids Query
# Ids Query 根据id列表查询 GET /_search {"query": {"ids" : {"type" : "t_doc","values" : ["1", "4", "100"]}} }
下面是复合查询
# bool查询【它有must、filter、should、must_not四个可选条件】 POST _search {"query": {"bool" : {"must" : {"term" : { "user" : "kimchy" }},"filter": {"term" : { "tag" : "tech" }},"must_not" : {"range" : {"age" : { "gte" : 10, "lte" : 20 }}},"should" : [{ "term" : { "tag" : "wow" } },{ "term" : { "tag" : "elasticsearch" } }],"minimum_should_match" : 1,"boost" : 1.0}} }
下面是地理查询,初始化数据 参见 19.2 geo_bounding_box查询 地图选点:这里
**地理边界查询【根据两个点确定的矩形,查询落在矩形内的坐标】
# 地理边界查询 GET /china_index/_search {"query": {"bool" : {"must" : {"match_all" : {}},"filter" : {"geo_bounding_box" : {"location" : {"top_left" : "23.1706638271,113.0383300781","bottom_right" : "22.9760953044,113.5025024414"}}}}} }
结果:
**地理半径查询【根据指定的坐标为中心,查询半径范围内的坐标】
# 地理半径查询 GET /china_index/_search {"query": {"bool" : {"must" : {"match_all" : {}},"filter" : {"geo_distance" : {"distance" : "20km","location" : {"lat" : 39.6733703918,"lon" : 116.4111328125}}}}} } --- {"took" : 6,"timed_out" : false,"_shards" : {"total" : 1,"successful" : 1,"skipped" : 0,"failed" : 0},"hits" : {"total" : 1,"max_score" : 1.0,"hits" : [{"_index" : "china_index","_type" : "city","_id" : "150","_score" : 1.0,"_source" : {"pName" : "北京市","cName" : "大兴区","location" : {"lat" : 39.72684,"lon" : 116.34159}}}]} }
**地理多边形查询【查找指定的坐标围成的多边形内的坐标】
# 地理多边形查询 GET /china_index/_search {"query": {"bool" : {"must" : {"match_all" : {}},"filter" : {"geo_polygon" : {"location" : {"points" : ["20.4270128143,110.2807617188","19.6632802200,109.7094726563","19.6839702359,110.8520507813"]}}}}} } --- {"took" : 39,"timed_out" : false,"_shards" : {"total" : 1,"successful" : 1,"skipped" : 0,"failed" : 0},"hits" : {"total" : 4,"max_score" : 1.0,"hits" : [{"_index" : "china_index","_type" : "city","_id" : "1555","_score" : 1.0,"_source" : {"pName" : "海南省","cName" : "海口","location" : {"lat" : 20.02,"lon" : 110.35}}},{"_index" : "china_index","_type" : "city","_id" : "1556","_score" : 1.0,"_source" : {"pName" : "海南省","cName" : "琼山","location" : {"lat" : 19.98,"lon" : 110.33}}},{"_index" : "china_index","_type" : "city","_id" : "1558","_score" : 1.0,"_source" : {"pName" : "海南省","cName" : "定安","location" : {"lat" : 19.68,"lon" : 110.31}}},{"_index" : "china_index","_type" : "city","_id" : "1562","_score" : 1.0,"_source" : {"pName" : "海南省","cName" : "澄迈","location" : {"lat" : 19.75,"lon" : 110.0}}}]} }
**地理形状查询 geo_shape【这个资料比较少,所以我重点研究了一下】
# 存储地理形状的索引 # tree参数:geohash和quadtree,默认geohash # strategy参数:recursive和term,默认recursive【支持查询:INTERSECTS,DISJOINT,WITHIN,CONTAINS】 # precision参数:精度,单位有in, inch, yd, yard, mi, miles, km, kilometers, m,meters, cm,centimeters, mm, millimeters # 形状类型解释 | GeoJSON Type | WKT Type | Elasticsearch Type # 单个地理坐标 Point POINT point # 给出两个或多个点的任意一条线 LineString LINESTRING linestring # 闭合的多边形,第一个和最后一个点必须匹配 Polygon POLYGON polygon # 一系列未连接但可能相关的点 MultiPoint MULTIPOINT multipoint # 一系列独立的线 MultiLineString MULTILINESTRING multilinestring # 一系列单独的多边形 MultiPolygon MULTIPOLYGON multipolygon # 类似于multi系列,但是多种类型不可以共存 GeometryCollection GEOMETRYCOLLECTION geometrycollection # 仅指定左上角和右下角的矩形 无 BBOX envelope # 指定中心和半径的圆,默认单位是米 无 无 circle PUT china_shape_index {"settings" : {"number_of_shards" : 1,"number_of_replicas" : 1},"mappings" : {"info" : {"properties" : {"remark" : { "type" : "keyword" },"location" : { "type" : "geo_shape","tree" : "geohash","precision": "100m"}}}} }
添加不同类型的数据
# 注意,如果是数组[经度,纬度] # 添加一个点 POST /china_shape_index/info {"location" : {"type" : "point","coordinates" : [109.1162109375,37.2653099556]} } # 添加一条线 POST /china_shape_index/info {"location" : {"type" : "linestring","coordinates" : [[109.1162109375,37.2653099556], [117.6855468750,35.5322262277]]} } # 添加一个形状【我画了个三角形】 POST /china_shape_index/info {"location" : {"type" : "polygon","coordinates" : [[ [114.0380859375, 31.9148675033], [116.6748046875, 30.0690939644], [111.4453125000,29.7643773752], [114.0380859375, 31.9148675033] ]]} } # 多个坐标 POST /china_shape_index/info {"location" : {"type" : "multipoint","coordinates" : [[111.4453125000,29.7643773752], [117.6855468750,35.5322262277]]} } # 由leftTop和bottomRight围成的矩形 POST /china_shape_index/info {"location" : {"type" : "envelope","coordinates" : [ [120.2783203125,25.2049411536], [122.2119140625,23.4430889311] ]} } # 圆形 POST /china_shape_index/info {"location" : {"type" : "circle","coordinates" : [116.5429687500,39.7071866568],"radius" : "10km"} }
形状查询【这里与我们测试数据(以北京为中心画一个圆)相交了】
# 查询相交的形状。relation可选:intersects, disjoint, within, contains【相交,不相交,内部,包含】 GET /china_shape_index/_search {"query":{"bool": {"must": {"match_all": {}},"filter": {"geo_shape": {"location": {"shape": {"type": "envelope","coordinates" : [[114.9169921875,40.5137991550], [118.6083984375,38.7883453551]]},"relation": "intersects"}}}}} } --- {"took" : 1,"timed_out" : false,"_shards" : {"total" : 1,"successful" : 1,"skipped" : 0,"failed" : 0},"hits" : {"total" : 1,"max_score" : 1.0,"hits" : [{"_index" : "china_shape_index","_type" : "info","_id" : "FbvH82cBOwlg01SCD5ab","_score" : 1.0,"_source" : {"location" : {"type" : "circle","coordinates" : [116.54296875,39.7071866568],"radius" : "10km"}}}]} }
..
Java【太多了,我只选择部分示例】
全文索引系列:matchQuery、matchAllQuery、matchPhraseQuery、matchPhrasePrefixQuery、multiMatchQuery、commonTermsQuery、queryStringQuery
Term系列:termQuery、termsQuery、rangeQuery、existsQuery、prefixQuery、wildcardQuery、regexpQuery、fuzzyQuery、typeQuery、idsQuery
地理系列:geoDistanceQuery、geoBoundingBoxQuery、geoPolygonQuery、geoShapeQuery
--
/*** matchQuery
* 排序,高亮查询* @return* @throws IOException*/public static RestHighLevelClient search() throws IOException {RestHighLevelClient client = Instance().getClient();try {SearchResponse search = client.search(new SearchRequest("test").source(new SearchSourceBuilder().query(QueryBuilders.matchQuery("message", "今天的主人公")).sort("_score", SortOrder.DESC) // 根据分数倒序排序.from(0) // 返回结果开始位置.size(5) // 返回结果数量.timeout(TimeValue.timeValueSeconds(10)) // 超时.highlighter(new HighlightBuilder().field("message",200).preTags("<pre>").postTags("</pre>"))), RequestOptions.DEFAULT);System.out.println("Hits:" + Hits().totalHits);Hits().forEach(e -> {System.out.println("分数:" + e.getScore() + ",结果:" + e.getSourceAsString());Map<String, HighlightField> highlightFields = e.getHighlightFields();for (String key : highlightFields.keySet()){HighlightField field = (key);System.out.println(key + ":" + field.fragments()[0]/* + "," + field.fragments().length*/);}});} catch (ElasticsearchException e) {if(e.status() == RestStatus.NOT_FOUND){// TODOSystem.out.println("Index Not Found-" + e.getIndex());}}return client;}
输出:
Hits:2 分数:3.421475,结果:{"message":"她就是我们今天的主人公,伊丽莎白·福尔摩斯(Elizabeth Holmes)。"} message:她就是我们<pre>今天</pre><pre>的</pre><pre>主人</pre><pre>公</pre>,伊丽莎白·福尔摩斯(Elizabeth Holmes)。 分数:0.26740497,结果:{"message":"她过山车一般的跌宕人生,成了 2018 年我听过的最精彩、也最让人感叹唏嘘的真人真事。"} message:她过山车一般<pre>的</pre>跌宕人生,成了 2018 年我听过<pre>的</pre>最精彩、也最让人感叹唏嘘<pre>的</pre>真人真事。
--
/*** matchPhraseQuery* 排序,高亮查询* @return* @throws IOException*/public static RestHighLevelClient search() throws IOException {RestHighLevelClient client = Instance().getClient();try {SearchResponse search = client.search(new SearchRequest("test").source(new SearchSourceBuilder().query(QueryBuilders.matchPhraseQuery("message", "今天的主人公")).sort("_score", SortOrder.DESC) // 根据分数倒序排序.from(0) // 返回结果开始位置.size(5) // 返回结果数量.timeout(TimeValue.timeValueSeconds(10)) // 超时.highlighter(new HighlightBuilder().field("message",200).preTags("<pre>").postTags("</pre>"))), RequestOptions.DEFAULT);System.out.println("Hits:" + Hits().totalHits);Hits().forEach(e -> {System.out.println("分数:" + e.getScore() + ",结果:" + e.getSourceAsString());Map<String, HighlightField> highlightFields = e.getHighlightFields();for (String key : highlightFields.keySet()){HighlightField field = (key);System.out.println(key + ":" + field.fragments()[0]/* + "," + field.fragments().length*/);}});} catch (ElasticsearchException e) {if(e.status() == RestStatus.NOT_FOUND){// TODOSystem.out.println("Index Not Found-" + e.getIndex());}}return client;}
结果:
Hits:1 分数:3.421475,结果:{"message":"她就是我们今天的主人公,伊丽莎白·福尔摩斯(Elizabeth Holmes)。"} message:她就是我们<pre>今天</pre><pre>的</pre><pre>主人</pre><pre>公</pre>,伊丽莎白·福尔摩斯(Elizabeth Holmes)。
--
/*** queryStringQuery* 排序,高亮查询* @return* @throws IOException*/public static RestHighLevelClient search() throws IOException {RestHighLevelClient client = Instance().getClient();try {SearchResponse search = client.search(new SearchRequest("test").source(new SearchSourceBuilder().query(QueryBuilders.queryStringQuery("今天的主人公").field("message")).sort("_score", SortOrder.DESC) // 根据分数倒序排序.from(0) // 返回结果开始位置.size(5) // 返回结果数量.timeout(TimeValue.timeValueSeconds(10)) // 超时.highlighter(new HighlightBuilder().field("message",200).preTags("<pre>").postTags("</pre>"))), RequestOptions.DEFAULT);System.out.println("Hits:" + Hits().totalHits);Hits().forEach(e -> {System.out.println("分数:" + e.getScore() + ",结果:" + e.getSourceAsString());Map<String, HighlightField> highlightFields = e.getHighlightFields();for (String key : highlightFields.keySet()){HighlightField field = (key);System.out.println(key + ":" + field.fragments()[0]/* + "," + field.fragments().length*/);}});} catch (ElasticsearchException e) {if(e.status() == RestStatus.NOT_FOUND){// TODOSystem.out.println("Index Not Found-" + e.getIndex());}}return client;}
结果:
Hits:2 分数:3.421475,结果:{"message":"她就是我们今天的主人公,伊丽莎白·福尔摩斯(Elizabeth Holmes)。"} message:她就是我们<pre>今天</pre><pre>的</pre><pre>主人</pre><pre>公</pre>,伊丽莎白·福尔摩斯(Elizabeth Holmes)。 分数:0.26740497,结果:{"message":"她过山车一般的跌宕人生,成了 2018 年我听过的最精彩、也最让人感叹唏嘘的真人真事。"} message:她过山车一般<pre>的</pre>跌宕人生,成了 2018 年我听过<pre>的</pre>最精彩、也最让人感叹唏嘘<pre>的</pre>真人真事。
下面测试term系列
# 准备测试数据 PUT users {"settings" : {"number_of_shards" : 1,"number_of_replicas" : 1},"mappings" : {"info" : {"properties" : {"username" : { "type" : "keyword" },"address" : { "type" : "text","analyzer": "ik_max_word" }}}} } PUT users/info/1 {"username" : "孙行者","address" : "软件产业基地1栋B座大堂","age": 15} PUT users/info/2 {"username" : "孙大圣","address" : "万达北路710号戈雅公寓105号商铺","age": 26} PUT users/info/3 {"username" : "西蒙·胡塞·德·拉·桑迪西玛·特里尼达·玻利瓦尔·帕拉修斯·伊·布兰科","address" : "滨河大道7009号","age": 7} PUT users/info/4 {"username" : "奥斯特洛夫斯基","address" : "光谷二路225号食堂","age": 30} PUT users/info/5 {"username" : "Brfxxccxxmnpcccclllmmnprxvclmnckssqlbb1111b","address" : "海淀紫竹院路甲2号商业05号","age": 18} # 查看 GET /users/_search
--
/*** termQuery* rangeQuery* prefixQuery* wildcardQuery* @return* @throws IOException*/public static RestHighLevelClient termSearch() throws IOException {RestHighLevelClient client = Instance().getClient();SearchRequest request = new SearchRequest("users");String[] includeFields = new String[] {"username", "age"};String[] excludeFields = new String[] {"addr*"};request.source(new SearchSourceBuilder()// 关键字查询//.sQuery("username", "奥斯特洛夫斯基"))// 范围查询//.query(QueryBuilders.rangeQuery("age").lt(20))// 前缀查询//.query(QueryBuilders.prefixQuery("username", "孙"))// 通配符查询.query(QueryBuilders.wildcardQuery("username", "西蒙*")).fetchSource(includeFields, excludeFields) // 过滤源.from(0).size(5).sort("age", SortOrder.ASC));SearchResponse search = client.search(request, RequestOptions.DEFAULT);System.out.println("Hits:" + Hits().totalHits);Hits().forEach(e -> {System.out.SourceAsString());});return client;}
结果:
Hits:1 {"age":7,"username":"西蒙·胡塞·德·拉·桑迪西玛·特里尼达·玻利瓦尔·帕拉修斯·伊·布兰科"}
下面测试聚合查询 Aggregation
/*** 聚合查询* @return* @throws IOException*/public static RestHighLevelClient aggSearch() throws IOException {RestHighLevelClient client = Instance().getClient();SearchRequest request = new SearchRequest("users");request.source(new SearchSourceBuilder().query(QueryBuilders.matchAllQuery()).aggregation(AggregationBuilders.avg("ageAVG").field("age")).from(0).size(5).sort("age", SortOrder.ASC));SearchResponse search = client.search(request, RequestOptions.DEFAULT);System.out.println("Hits:" + Hits().totalHits);Hits().forEach(e -> {System.out.SourceAsString());});Avg avg = Aggregations().get("ageAVG");System.out.println("平均值:" + Value());return client;}
结果:
Hits:5 {"username":"西蒙·胡塞·德·拉·桑迪西玛·特里尼达·玻利瓦尔·帕拉修斯·伊·布兰科","address":"滨河大道7009号","age":7} {"username":"孙行者","address":"软件产业基地1栋B座大堂","age":15} {"username":"Brfxxccxxmnpcccclllmmnprxvclmnckssqlbb1111b","address":"海淀紫竹院路甲2号商业05号","age":18} {"username":"孙大圣","address":"万达北路710号戈雅公寓105号商铺","age":26} {"username":"奥斯特洛夫斯基","address":"光谷二路225号食堂","age":30} 平均值:19.2
下面测试复合查询 bool
/*** 复合查询* @return* @throws IOException*/public static RestHighLevelClient boolSearch() throws IOException {RestHighLevelClient client = Instance().getClient();SearchRequest request = new SearchRequest("users");request.source(new SearchSourceBuilder().query(QueryBuilders.boolQuery().must(QueryBuilders.rangeQuery("age").gt(20)).Query("username","孙大圣"))).from(0).size(5).sort("age", SortOrder.ASC));SearchResponse search = client.search(request, RequestOptions.DEFAULT);System.out.println("Hits:" + Hits().totalHits);Hits().forEach(e -> {System.out.SourceAsString());});return client;}
结果:
Hits:1 {"username":"奥斯特洛夫斯基","address":"光谷二路225号食堂","age":30}
下面测试地理查询
--矩形
public static RestHighLevelClient geoSearch() throws IOException {RestHighLevelClient client = Instance().getClient();SearchRequest request = new SearchRequest("china_index");request.source(new SearchSourceBuilder()// 地理边界查询,设置字段名,top Left和bottom Right.BoundingBoxQuery("location").setCorners(23.1706638271,113.0383300781,22.9760953044,113.5025024414)).from(0).size(100));SearchResponse search = client.search(request, RequestOptions.DEFAULT);System.out.println("Hits:" + Hits().totalHits);Hits().forEach(e -> {System.out.SourceAsString());});return client;}
结果:
Hits:9 {"pName":"广东省","cName":"广州","location":{"lat":23.12908,"lon":113.26436}} {"pName":"广东省","cName":"越秀","location":{"lat":23.12901,"lon":113.2668}} {"pName":"广东省","cName":"荔湾","location":{"lat":23.12586,"lon":113.24428}} {"pName":"广东省","cName":"海珠","location":{"lat":23.08331,"lon":113.3172}} {"pName":"广东省","cName":"天河","location":{"lat":23.12463,"lon":113.36199}} {"pName":"广东省","cName":"白云","location":{"lat":23.157032,"lon":113.273238}} {"pName":"广东省","cName":"佛山","location":{"lat":23.02185,"lon":113.12192}} {"pName":"广东省","cName":"禅城","location":{"lat":23.00944,"lon":113.12249}} {"pName":"广东省","cName":"南海","location":{"lat":23.02882,"lon":113.14278}}
--圆形
public static RestHighLevelClient geoSearch() throws IOException {RestHighLevelClient client = Instance().getClient();SearchRequest request = new SearchRequest("china_index");List<GeoPoint> list = new ArrayList<>();list.add(new GeoPoint(20.4270128143,110.2807617188));list.add(new GeoPoint(19.6632802200,109.7094726563));list.add(new GeoPoint(19.6839702359,110.8520507813));request.source(new SearchSourceBuilder()// 地理半径查询,设置字段名,纬度,经度,距离,距离类型.DistanceQuery("location").point(39.6733703918,116.4111328125).distance(50, DistanceUnit.KILOMETERS)).from(0).size(100));SearchResponse search = client.search(request, RequestOptions.DEFAULT);System.out.println("Hits:" + Hits().totalHits);Hits().forEach(e -> {System.out.SourceAsString());});return client;}
结果:
Hits:15 {"pName":"北京市","cName":"东城区","location":{"lat":39.92855,"lon":116.41637}} {"pName":"北京市","cName":"西城区","location":{"lat":39.91231,"lon":116.36611}} {"pName":"北京市","cName":"朝阳区","location":{"lat":39.927289,"lon":116.4498}} {"pName":"北京市","cName":"丰台区","location":{"lat":39.85856,"lon":116.28616}} {"pName":"北京市","cName":"石景山区","location":{"lat":39.90569,"lon":116.22299}} {"pName":"北京市","cName":"海淀区","location":{"lat":39.95933,"lon":116.29845}} {"pName":"北京市","cName":"通州区","location":{"lat":39.916195,"lon":116.662852}} {"pName":"北京市","cName":"大兴区","location":{"lat":39.72684,"lon":116.34159}} {"pName":"北京市","cName":"房山区","location":{"lat":39.74788,"lon":116.14294}} {"pName":"北京市","cName":"门头沟区","location":{"lat":39.94048,"lon":116.10146}} {"pName":"河北省","cName":"涿县","location":{"lat":39.48,"lon":115.98}} {"pName":"河北省","cName":"廊坊","location":{"lat":39.53,"lon":116.7}} {"pName":"河北省","cName":"安次","location":{"lat":39.52,"lon":116.69}} {"pName":"河北省","cName":"固安","location":{"lat":39.44,"lon":116.29}} {"pName":"河北省","cName":"永清","location":{"lat":39.32,"lon":116.48}}
--多边形
public static RestHighLevelClient geoSearch() throws IOException {RestHighLevelClient client = Instance().getClient();SearchRequest request = new SearchRequest("china_index");List<GeoPoint> list = new ArrayList<>();list.add(new GeoPoint(20.4270128143,110.2807617188));list.add(new GeoPoint(19.6632802200,109.7094726563));list.add(new GeoPoint(19.6839702359,110.8520507813));request.source(new SearchSourceBuilder()// 地理形状查询,设置字段名,围成多边形状的坐标列表.PolygonQuery("location", list)).from(0).size(100));SearchResponse search = client.search(request, RequestOptions.DEFAULT);System.out.println("Hits:" + Hits().totalHits);Hits().forEach(e -> {System.out.SourceAsString());});return client;}
结果:
Hits:4 {"pName":"海南省","cName":"海口","location":{"lat":20.02,"lon":110.35}} {"pName":"海南省","cName":"琼山","location":{"lat":19.98,"lon":110.33}} {"pName":"海南省","cName":"定安","location":{"lat":19.68,"lon":110.31}} {"pName":"海南省","cName":"澄迈","location":{"lat":19.75,"lon":110.0}}
-- geo_shape查询
/*** 地理形状查询* .html* 已知Builder实现:CircleBuilder, EnvelopeBuilder, GeometryCollectionBuilder, LineStringBuilder, MultiLineStringBuilder, MultiPointBuilder, MultiPolygonBuilder, PointBuilder, PolygonBuilder* @return* @throws IOException*/public static RestHighLevelClient geoShapeSearch() throws IOException {RestHighLevelClient client = Instance().getClient();SearchRequest request = new SearchRequest("china_shape_index");request.source(new SearchSourceBuilder().ShapeQuery("location",// 查询类型为envelope就用EnvelopeBuilder. topLeft,bottomRight. new Coordinate(经度,纬度)new EnvelopeBuilder(new Coordinate(114.9169921875,40.5137991550),new Coordinate(118.6083984375,38.7883453551))).relation(ShapeRelation.INTERSECTS))// ShapeBuilders已经过时,不推荐使用了//.ShapeQuery("location",wEnvelope(new Coordinate(114.9169921875,40.5137991550),new Coordinate(118.6083984375,38.7883453551)))).from(0).size(100));SearchResponse search = client.search(request, RequestOptions.DEFAULT);System.out.println("Hits:" + Hits().totalHits);Hits().forEach(e -> {System.out.SourceAsString());});return client;}
结果:
Hits:1 {"location":{"type":"circle","coordinates":[116.54296875,39.7071866568],"radius":"10km"}}
**search scroll
/*** scrollSearch* @return* @throws IOException*/public static RestHighLevelClient scrollSearch() throws IOException {RestHighLevelClient client = Instance().getClient();// 设置超时final Scroll scroll = new Scroll(TimeValue.timeValueMinutes(1L));SearchRequest request = new SearchRequest("books");request.source(new SearchSourceBuilder().query(QueryBuilders.matchAllQuery()).sort("_id",SortOrder.ASC).size(500)) // 每批大小.scroll(scroll); // 设置scrollSearchResponse searchResponse = client.search(request, RequestOptions.DEFAULT); // 执行查询String scrollId = ScrollId();SearchHit[] hits = Hits().getHits();while(hits != null && hits.length > 0) {System.out.println("========Begin=======");for (SearchHit hit : hits) {System.out.SourceAsString());}System.out.println("========End=======");System.out.println("Size:" + hits.length + ",Scroll:" + scrollId);SearchScrollRequest scrollRequest = new SearchScrollRequest(scrollId).scroll(scroll); // 设置SearchScrollRequestsearchResponse = client.scroll(scrollRequest, RequestOptions.DEFAULT); // 拉取新的数据scrollId = ScrollId();hits = Hits().getHits();};// 当scroll超时时,Search Scroll API使用的搜索上下文将自动删除ClearScrollRequest clearScrollRequest = new ClearScrollRequest();clearScrollRequest.addScrollId(scrollId);ClearScrollResponse clearScrollResponse = client.clearScroll(clearScrollRequest, RequestOptions.DEFAULT);boolean succeeded = clearScrollResponse.isSucceeded();System.out.println("ClearScroll:" + succeeded);return client;}
结果:【一共2000条,省略了部分结果】
========Begin======= {"title":"title_1","user":"user_1"} {"title":"title_10","user":"user_10"} {"title":"title_100","user":"user_100"} {"title":"title_1000","user":"user_1000"} ... {"title":"title_1448","user":"user_1448"} ========End======= Size:500,Scroll:DnF1ZXJ5VGhlbkZldGNoBQAAAAAAAM7QFndDcjZVejBqVHZHYVRIaDVhY054S0EAAAAAAADOzxZ3Q3I2VXowalR2R2FUSGg1YWNOeEtBAAAAAAAAztEWd0NyNlV6MGpUdkdhVEhoNWFjTnhLQQAAAAAAAM7SFndDcjZVejBqVHZHYVRIaDVhY054S0EAAAAAAADO0xZ3Q3I2VXowalR2R2FUSGg1YWNOeEtB ========Begin======= ... {"title":"title_1899","user":"user_1899"} ========End======= Size:500,Scroll:DnF1ZXJ5VGhlbkZldGNoBQAAAAAAAM7QFndDcjZVejBqVHZHYVRIaDVhY054S0EAAAAAAADOzxZ3Q3I2VXowalR2R2FUSGg1YWNOeEtBAAAAAAAAztEWd0NyNlV6MGpUdkdhVEhoNWFjTnhLQQAAAAAAAM7SFndDcjZVejBqVHZHYVRIaDVhY054S0EAAAAAAADO0xZ3Q3I2VXowalR2R2FUSGg1YWNOeEtB ========Begin======= {"title":"title_19","user":"user_19"} ... {"title":"title_548","user":"user_548"} ========End======= Size:500,Scroll:DnF1ZXJ5VGhlbkZldGNoBQAAAAAAAM7QFndDcjZVejBqVHZHYVRIaDVhY054S0EAAAAAAADOzxZ3Q3I2VXowalR2R2FUSGg1YWNOeEtBAAAAAAAAztEWd0NyNlV6MGpUdkdhVEhoNWFjTnhLQQAAAAAAAM7SFndDcjZVejBqVHZHYVRIaDVhY054S0EAAAAAAADO0xZ3Q3I2VXowalR2R2FUSGg1YWNOeEtB ========Begin======= {"title":"title_549","user":"user_549"} ... {"title":"title_6","user":"user_6"} {"title":"title_60","user":"user_60"} {"title":"title_600","user":"user_600"} ... {"title":"title_699","user":"user_699"} {"title":"title_7","user":"user_7"} {"title":"title_70","user":"user_70"} {"title":"title_700","user":"user_700"} ... {"title":"title_799","user":"user_799"} {"title":"title_8","user":"user_8"} {"title":"title_80","user":"user_80"} {"title":"title_800","user":"user_800"} ... {"title":"title_899","user":"user_899"} {"title":"title_9","user":"user_9"} {"title":"title_90","user":"user_90"} {"title":"title_900","user":"user_900"} ... {"title":"title_999","user":"user_999"} ========End======= Size:500,Scroll:DnF1ZXJ5VGhlbkZldGNoBQAAAAAAAM7QFndDcjZVejBqVHZHYVRIaDVhY054S0EAAAAAAADOzxZ3Q3I2VXowalR2R2FUSGg1YWNOeEtBAAAAAAAAztEWd0NyNlV6MGpUdkdhVEhoNWFjTnhLQQAAAAAAAM7SFndDcjZVejBqVHZHYVRIaDVhY054S0EAAAAAAADO0xZ3Q3I2VXowalR2R2FUSGg1YWNOeEtB ClearScroll:true
**Multi-Search
HTTP请求
# 格式:一行header一行body GET users/_msearch {} {"query": {"terms" : { "username" : ["孙行者", "孙大圣"]}}} {} {"query": {"term" : { "username" : "Brfxxccxxmnpcccclllmmnprxvclmnckssqlbb1111b"}}} --- {"responses" : [{"took" : 0,"timed_out" : false,"_shards" : {"total" : 1,"successful" : 1,"skipped" : 0,"failed" : 0},"hits" : {"total" : 2,"max_score" : 1.0,"hits" : [{"_index" : "users","_type" : "info","_id" : "1","_score" : 1.0,"_source" : {"username" : "孙行者","address" : "软件产业基地1栋B座大堂","age" : 15}},{"_index" : "users","_type" : "info","_id" : "2","_score" : 1.0,"_source" : {"username" : "孙大圣","address" : "万达北路710号戈雅公寓105号商铺","age" : 26}}]},"status" : 200},{"took" : 0,"timed_out" : false,"_shards" : {"total" : 1,"successful" : 1,"skipped" : 0,"failed" : 0},"hits" : {"total" : 1,"max_score" : 1.3862944,"hits" : [{"_index" : "users","_type" : "info","_id" : "5","_score" : 1.3862944,"_source" : {"username" : "Brfxxccxxmnpcccclllmmnprxvclmnckssqlbb1111b","address" : "海淀紫竹院路甲2号商业05号","age" : 18}}]},"status" : 200}] }
Java
public static RestHighLevelClient multiSearch() throws IOException {RestHighLevelClient client = Instance().getClient();MultiSearchRequest request = new MultiSearchRequest();// 第一个查询SearchRequest firstSearchRequest = new SearchRequest("users");firstSearchRequest.source(new SearchSourceBuilder().sQuery("username","孙大圣")));request.add(firstSearchRequest);// 第二个查询SearchRequest secondSearchRequest = new SearchRequest("users");secondSearchRequest.source(new SearchSourceBuilder().query(QueryBuilders.prefixQuery("username", "Brfxx")));request.add(secondSearchRequest);MultiSearchResponse msearch = client.msearch(request, RequestOptions.DEFAULT);MultiSearchResponse.Item[] responses = Responses();for (MultiSearchResponse.Item i : responses){System.out.println("========" + i.getResponse().status().name());i.getResponse().getHits().forEach(e -> {System.out.SourceAsString());});}return client;}
结果:
========OK {"username":"孙大圣","address":"万达北路710号戈雅公寓105号商铺","age":26} ========OK {"username":"Brfxxccxxmnpcccclllmmnprxvclmnckssqlbb1111b","address":"海淀紫竹院路甲2号商业05号","age":18}
HTTP请求
GET _cluster/health --- {"cluster_name" : "my-elasticsearch","status" : "yellow","timed_out" : false,"number_of_nodes" : 1,"number_of_data_nodes" : 1,"active_primary_shards" : 15,"active_shards" : 15,"relocating_shards" : 0,"initializing_shards" : 0,"unassigned_shards" : 14,"delayed_unassigned_shards" : 0,"number_of_pending_tasks" : 0,"number_of_in_flight_fetch" : 0,"task_max_waiting_in_queue_millis" : 0,"active_shards_percent_as_number" : 51.724137931034484 }
获取集群状态
GET /_cluster/state --- {"cluster_name" : "my-elasticsearch","compressed_size_in_bytes" : 14766,"cluster_uuid" : "QmDZ773JR_ip0AN6jEdWtA","version" : 33,"state_uuid" : "l8WJu9BzTfGsIKba_gsodA","master_node" : "wCr6Uz0jTvGaTHh5acNxKA","blocks" : { },"nodes" : {"wCr6Uz0jTvGaTHh5acNxKA" : {"name" : "wCr6Uz0","ephemeral_id" : "qFZoP0iWQDm3EWM3TDb_vg","transport_address" : "127.0.0.1:9300","attributes" : {"ml.machine_memory" : "8510087168","xpack.installed" : "true","ml.max_open_jobs" : "20",abled" : "true"}}}, ... }
GET /_cluster/stats?human&prettyGET /_cluster/settings# 设置集群settings # 1. transient cluster settings # 2. persistent cluster settings # 3. settings in l configuration file. PUT /_cluster/settings {"persistent" : {very.max_bytes_per_sec" : "50mb"} }# explain索引【三个参数必须的】 GET /_cluster/allocation/explain {"index": "china_index","shard": 0,"primary": true }# 节点统计数据 GET /_nodes/stats GET /_nodes/nodeId1,nodeId2/stats# return just indices GET /_nodes/stats/indices# return just os and process GET /_nodes/stats/os,process# return just process for node with IP address 10.0.0.1 GET /_nodes/10.0.0.1/stats/process# 每个节点的实用信息 GET _nodes/usage GET _nodes/nodeId1,nodeId2/usage
Java
/*** 集群信息* @return*/public static RestHighLevelClient info() throws IOException {RestHighLevelClient client = Instance().getClient();boolean ping = client.ping(RequestOptions.DEFAULT);System.out.println("Ping:" + ping);MainResponse info = client.info(RequestOptions.DEFAULT);ClusterName clusterName = ClusterName();String clusterUuid = ClusterUuid();String nodeName = NodeName();Version version = Version();Build build = Build();System.out.println("集群名称:" + clusterName.value());System.out.println("Uuid:" + clusterUuid);System.out.println("节点名称:" + nodeName);System.out.println("Version:" + String());System.out.println("Bulid:" + String());return client;}
结果:
Ping:true 集群名称:my-elasticsearch Uuid:QmDZ773JR_ip0AN6jEdWtA 节点名称:wCr6Uz0 Version:6.5.0 Bulid:[default][zip][816e6f6][2018-11-09T18:58:36.352602Z]
14.1 分词器
# 标准分词器 GET _analyze {"analyzer" : "standard","text" : ["this is a test", "the second text"] } # IK分词器 GET _analyze {"analyzer" : "ik_smart","text" : ["真好玩", "一个叫yado的博士找到他,希望buzzo和他的团伙去帮他散布一种叫做joy的毒品"] }
--
/*** 分词器* @return* @throws IOException*/public static RestHighLevelClient analyze() throws IOException {RestHighLevelClient client = Instance().getClient();AnalyzeRequest request = new AnalyzeRequest();("真好玩", "一个叫yado的博士找到他,希望buzzo和他的团伙去帮他散布一种叫做joy的毒品");request.analyzer("ik_smart");AnalyzeResponse response = client.indices().analyze(request, RequestOptions.DEFAULT);List<AnalyzeResponse.AnalyzeToken> tokens = Tokens();for(AnalyzeResponse.AnalyzeToken t : tokens){int endOffset = t.getEndOffset();int position = t.getPosition();int positionLength = t.getPositionLength();int startOffset = t.getStartOffset();String term = t.getTerm();String type = t.getType();System.out.println("Start:" + startOffset + ",End:" + endOffset + ",Position:" + position + ",Length:" + positionLength +",Term:" + term + ",Type:" + type);}return client;}
结果:
Start:0,End:3,Position:0,Length:1,Term:真好玩,Type:CN_WORD Start:4,End:6,Position:1,Length:1,Term:一个,Type:CN_WORD Start:6,End:7,Position:2,Length:1,Term:叫,Type:CN_CHAR Start:7,End:11,Position:3,Length:1,Term:yado,Type:ENGLISH Start:11,End:12,Position:4,Length:1,Term:的,Type:CN_CHAR Start:12,End:14,Position:5,Length:1,Term:博士,Type:CN_WORD Start:14,End:15,Position:6,Length:1,Term:找,Type:CN_CHAR Start:15,End:17,Position:7,Length:1,Term:到他,Type:CN_WORD Start:18,End:20,Position:8,Length:1,Term:希望,Type:CN_WORD Start:20,End:25,Position:9,Length:1,Term:buzzo,Type:ENGLISH Start:25,End:27,Position:10,Length:1,Term:和他,Type:CN_WORD Start:27,End:28,Position:11,Length:1,Term:的,Type:CN_CHAR Start:28,End:30,Position:12,Length:1,Term:团伙,Type:CN_WORD Start:30,End:31,Position:13,Length:1,Term:去,Type:CN_CHAR Start:31,End:32,Position:14,Length:1,Term:帮,Type:CN_CHAR Start:32,End:33,Position:15,Length:1,Term:他,Type:CN_CHAR Start:33,End:35,Position:16,Length:1,Term:散布,Type:CN_WORD Start:35,End:37,Position:17,Length:1,Term:一种,Type:CN_WORD Start:37,End:39,Position:18,Length:1,Term:叫做,Type:CN_WORD Start:39,End:42,Position:19,Length:1,Term:joy,Type:ENGLISH Start:42,End:43,Position:20,Length:1,Term:的,Type:CN_CHAR Start:43,End:45,Position:21,Length:1,Term:毒品,Type:CN_WORD
14.2 Create Index
创建索引限制
小写字母不能包含 , /, *, ?, ", <, >, |, ` ` (space character), ,, #7.0之前的索引可能包含冒号(:),但是不赞成这样做,7.0+不支持这样做不能以-,_,+开头不能. or ..长度不能超过255字节
HTTP请求
# 创建索引 PUT twitter {"settings" : {"number_of_shards" : 3,"number_of_replicas" : 2},"mappings" : {"my_doc" : {"properties" : {"field1" : { "type" : "text" }}}} }
Java
public static RestHighLevelClient createIndex() throws IOException {RestHighLevelClient client = Instance().getClient();CreateIndexRequest request = new CreateIndexRequest("twitter");request.settings(Settings.builder().put("index.number_of_shards", 3).put("index.number_of_replicas", 2))// 设置mapping//.mapping("t_doc", "field1","type=keyword,store=true") // Object key-pairs.mapping("t_doc", jsonBuilder().startObject().startObject("t_doc").startObject("properties").startObject("msg").field("type","text").endObject().endObject().endObject().endObject())// 别名.alias(new Alias("my_index_alias"))// 创建超时.timeout(TimeValue.timeValueMinutes(2))// 连接到主节点超时时间.masterNodeTimeout(TimeValue.timeValueMinutes(1))// 在创建索引返回响应之前等待的活动碎片副本的数量.waitForActiveShards(2);CreateIndexResponse indexResponse = client.indices().create(request, RequestOptions.DEFAULT);boolean acknowledged = indexResponse.isAcknowledged();boolean shardsAcknowledged = indexResponse.isShardsAcknowledged();System.out.println(acknowledged);return client;}
14.3 Delete Index
# 删除索引 DELETE /twitter
Java
public static RestHighLevelClient deleteIndex() throws IOException {RestHighLevelClient client = Instance().getClient();DeleteIndexRequest request = new DeleteIndexRequest(); // 使用_all或者通配符*可以删除所有索引。如果要禁用:action.destructive_requires_name=truerequest.indices("twitter","it_book","car","school","story");try {AcknowledgedResponse acknowledgedResponse = client.indices().delete(request, RequestOptions.DEFAULT);boolean acknowledged = acknowledgedResponse.isAcknowledged();System.out.println(acknowledged);} catch (ElasticsearchException exception) {if (exception.status() == RestStatus.NOT_FOUND) {println("Index Not Found");}}return client;}
14.4 Indices Exists
# 索引是否存在 HEAD /china_index # Type是否存在 HEAD /china_index/_mapping/city
Java
public static RestHighLevelClient existIndex() throws IOException {RestHighLevelClient client = Instance().getClient();GetIndexRequest request = new GetIndexRequest();request.indices("china_index");boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);System.out.println(exists);return client;}
14.5 Open Index
# 开启索引 POST /twitter/_open
Java
public static RestHighLevelClient openIndex() throws IOException {RestHighLevelClient client = Instance().getClient();OpenIndexRequest request = new OpenIndexRequest("twitter");request.timeout(TimeValue.timeValueMinutes(2));OpenIndexResponse open = client.indices().open(request, RequestOptions.DEFAULT);boolean acknowledged = open.isAcknowledged();boolean shardsAcked = open.isShardsAcknowledged();System.out.println(acknowledged);return client;}
14.6 Close Index
# 关闭索引 POST /twitter/_close
Java
public static RestHighLevelClient closeIndex() throws IOException {RestHighLevelClient client = Instance().getClient();CloseIndexRequest request = new CloseIndexRequest("twitter");request.timeout(TimeValue.timeValueMinutes(2));AcknowledgedResponse closeIndexResponse = client.indices().close(request, RequestOptions.DEFAULT);boolean acknowledged = closeIndexResponse.isAcknowledged();System.out.println(acknowledged);return client;}
14.7 Shrink Index【压缩索引】
# 准备源索引 PUT my_source_index {"settings" : {"number_of_shards" : 4,"number_of_replicas" : 2,"index.blocks.write": true} } -- {"acknowledged" : true,"shards_acknowledged" : true,"index" : "my_source_index" }
压缩操作
POST my_source_index/_shrink/my_target_index?copy_settings=true {"settings": {"index.number_of_shards": 1, "index.number_of_replicas": 1,dec": "best_compression" },"aliases": {"my_search_indices": {}} } -- {"acknowledged" : true,"shards_acknowledged" : true,"index" : "my_target_index" }
查看索引信息
GET my_source_index 结果: {"my_source_index" : {"aliases" : { },"mappings" : { },"settings" : {"index" : {"number_of_shards" : "4","blocks" : {"write" : "true"},"provided_name" : "my_source_index","creation_date" : "1546589291669","number_of_replicas" : "2","uuid" : "tSYNLldWQNCOlR5NJGaH9g","version" : {"created" : "6050099"}}}} } --- GET my_target_index 结果: {"my_target_index" : {"aliases" : {"my_search_indices" : { }},"mappings" : { },"settings" : {"index" : {"allocation" : {"max_retries" : "1"},"shrink" : {"source" : {"name" : "my_source_index","uuid" : "tSYNLldWQNCOlR5NJGaH9g"}},"blocks" : {"write" : "true"},"provided_name" : "my_target_index","creation_date" : "1546589354014","number_of_replicas" : "1","uuid" : "F976xviGQ965JU9patwQnA","version" : {"created" : "6050099","upgraded" : "6050099"},"codec" : "best_compression","routing" : {"allocation" : {"initial_recovery" : {"_id" : "wCr6Uz0jTvGaTHh5acNxKA"}}},"number_of_shards" : "1","routing_partition_size" : "1","resize" : {"source" : {"name" : "my_source_index","uuid" : "tSYNLldWQNCOlR5NJGaH9g"}}}}} }
Java
/*** 压缩索引(将索引压缩为主分片数更少的新索引)* 目标索引中请求的主碎片数量必须是源索引中碎片数量的一个因数。例如,有8个主碎片的索引可以压缩为4个、2个或1个主碎片;* 或者有15个主碎片的索引可以压缩为5个、3个或1个主碎片。* 过程:* 首先,它创建一个新的目标索引,其定义与源索引相同,但是主碎片的数量较少* 然后它将段从源索引硬链接到目标索引* 最后,它将目标索引恢复为一个刚刚重新打开的closed index* @return*/public static RestHighLevelClient shrinkIndex() throws IOException {RestHighLevelClient client = Instance().getClient();ResizeRequest resizeRequest = new ResizeRequest("target_index", "source_index");TargetIndexRequest().alias(new Alias("target_index_alias")).settings(Settings.builder().put("index.number_of_shards", 2));ResizeResponse resizeResponse = client.indices().shrink(resizeRequest, RequestOptions.DEFAULT);boolean acknowledged = resizeResponse.isAcknowledged();boolean shardsAcked = resizeResponse.isShardsAcknowledged();System.out.println(acknowledged);return client;}
14.8 Split Index
准备数据
# index.number_of_routing_shards must be >= index.number_of_shards PUT my_source_index2 {"settings" : {"number_of_shards" : 2,"index.number_of_routing_shards" : 8,"index.blocks.write": true} } -- {"acknowledged" : true,"shards_acknowledged" : true,"index" : "my_source_index2" }
拆分
# 拆分索引 POST my_source_index2/_split/my_target_index2?copy_settings=true {"settings": {"index.number_of_shards": 4},"aliases": {"my_search_indices": {}} } -- {"acknowledged" : true,"shards_acknowledged" : true,"index" : "my_target_index2" }
查看索引
GET my_source_index2 结果: {"my_source_index2" : {"aliases" : { },"mappings" : { },"settings" : {"index" : {"number_of_shards" : "2","blocks" : {"write" : "true"},"provided_name" : "my_source_index2","creation_date" : "1546590226265","number_of_replicas" : "1","uuid" : "iuDENl3uQku0Ef6flu8S-Q","version" : {"created" : "6050099"}}}} } --- GET my_target_index2 结果: {"my_target_index2" : {"aliases" : {"my_search_indices" : { }},"mappings" : { },"settings" : {"index" : {"number_of_shards" : "4","routing_partition_size" : "1","blocks" : {"write" : "true"},"provided_name" : "my_target_index2","resize" : {"source" : {"name" : "my_source_index2","uuid" : "iuDENl3uQku0Ef6flu8S-Q"}},"creation_date" : "1546590255143","number_of_replicas" : "1","uuid" : "ZBnocs2bSker45kb2lXoRw","version" : {"created" : "6050099","upgraded" : "6050099"}}}} }
Java
/*** 拆分索引(每个原始的主碎片被拆分为新索引中的两个或多个主碎片)* 重要:源索引必须在创建的时候指定number_of_routing_shards参数,以便将来有拆分的需要。在Elasticsearch 7.0这个前提被移除。* 索引能被拆分的次数以及每个主分片能被拆分的个数取决于index.number_of_routing_shards参数的设置* 过程:* 首先,它创建一个新的目标索引,其定义与源索引相同,但是具有更多的主碎片* 然后它将段从源索引硬链接到目标索引* 创建了低级文件之后,所有文档将再次散列以删除属于不同碎片的文档* 最后,它将目标索引恢复为一个刚刚重新打开的closed index* @return*/public static RestHighLevelClient splitIndex() throws IOException {RestHighLevelClient client = Instance().getClient();ResizeRequest resizeRequest = new ResizeRequest("target_index", "source_index");resizeRequest.timeout(TimeValue.timeValueSeconds(2)).masterNodeTimeout(TimeValue.timeValueMinutes(1)).setResizeType(ResizeType.SPLIT); // 类型是拆分 TargetIndexRequest().alias(new Alias("target_index_alias")).settings(Settings.builder().put("index.number_of_shards", 4));ResizeResponse resizeResponse = client.indices().split(resizeRequest, RequestOptions.DEFAULT);boolean acknowledged = resizeResponse.isAcknowledged();boolean shardsAcked = resizeResponse.isShardsAcknowledged();return client;}
14.9 Refresh
# 刷新索引【默认定期刷新】 POST /kimchy,elasticsearch/_refresh POST /_refresh
--
/*** 刷新索引* 默认情况下,刷新是定期调度的* @return*/public static RestHighLevelClient refreshIndex() throws IOException {RestHighLevelClient client = Instance().getClient();RefreshRequest refreshRequest = new RefreshRequest("index_1","index_2");try {RefreshResponse refresh = client.indices().refresh(refreshRequest, RequestOptions.DEFAULT);int totalShards = TotalShards();int successfulShards = SuccessfulShards();int failedShards = FailedShards();DefaultShardOperationFailedException[] failures = ShardFailures();} catch (ElasticsearchException exception) {if (exception.status() == RestStatus.NOT_FOUND) {// TODO }}return client;}
14.10 Flush
POST twitter/_flush
---
/*** .html* 索引的刷新进程通过将数据刷新到索引存储并清除内部事务日志,基本上将内存从索引中释放出来* @return* @throws IOException*/public static RestHighLevelClient flushIndex() throws IOException {RestHighLevelClient client = Instance().getClient();FlushRequest requestMultiple = new FlushRequest("index1", "index2");try {FlushResponse flushResponse = client.indices().flush(requestMultiple, RequestOptions.DEFAULT);int totalShards = TotalShards();int successfulShards = SuccessfulShards();int failedShards = FailedShards();DefaultShardOperationFailedException[] failures = ShardFailures();} catch (ElasticsearchException exception) {if (exception.status() == RestStatus.NOT_FOUND) {// TODO }}return client;}
14.11 Clear Cache
# 清空缓存 POST /twitter/_cache/clear
---
/*** 清除索引的缓存* @return*/public static RestHighLevelClient clearCacheIndex() throws IOException {RestHighLevelClient client = Instance().getClient();ClearIndicesCacheRequest cacheRequest = new ClearIndicesCacheRequest("index1", "index2");cacheRequest.queryCache(true); // 查询cacheRequest.fieldDataCache(true); // 字段数据questCache(true); // 请求cacheRequest.fields("field1", "field2", "field3");try {ClearIndicesCacheResponse clearCache = client.indices().clearCache(cacheRequest, RequestOptions.DEFAULT);int totalShards = TotalShards();int successfulShards = SuccessfulShards();int failedShards = FailedShards();DefaultShardOperationFailedException[] failures = ShardFailures();} catch (ElasticsearchException exception) {if (exception.status() == RestStatus.NOT_FOUND) {// TODO }}return client;}
14.12 Force Merge
Http
# 合并 POST /kimchy/_forcemerge?only_expunge_deletes=false&max_num_segments=100&flush=true # max_num_segments=1,所有的段都重写为一个新的 POST /kimchy,elasticsearch/_forcemerge
Java
/*** 合并一个或多个索引* 此调用将阻塞,直到合并完成。如果http连接丢失,请求将在后台继续,任何新请求都将阻塞,直到前一个强制合并完成* **强制合并只能对只读索引调用。对读写索引执行强制合并会导致产生非常大的段(每段大于5GB)* .html* .html* @return*/public static RestHighLevelClient ForceMergeIndex() throws IOException {RestHighLevelClient client = Instance().getClient();ForceMergeRequest requestMultiple = new ForceMergeRequest("index1", "index2");// 要合并的分片数。要完全合并索引,请将其设置为1requestMultiple.maxNumSegments(1);// 合并过程是否删除标记为删除的段。在Lucene中,一个文档不是从一个段中删除,而是标记为已删除。在段的合并过程中,将创建一个没有这些删除的新段。// 此标志只允许合并具有删除的段。默认值为lyExpungeDeletes(true);requestMultiple.flush(true);try {ForceMergeResponse forceMergeResponse = client.indices().forcemerge(requestMultiple, RequestOptions.DEFAULT);int totalShards = TotalShards();int successfulShards = SuccessfulShards();int failedShards = FailedShards();DefaultShardOperationFailedException[] failures = ShardFailures();} catch (ElasticsearchException exception) {if (exception.status() == RestStatus.NOT_FOUND) {// TODO }}return client;}
14.13 Put Mapping
HTTP
# 增加一个不带type的索引 PUT twitter {} # 增加type PUT twitter/_mapping/_doc {"properties": {"email": {"type": "keyword"}} }
Java
/*** 添加mapping(不能更新已存在的字段类型)* @return*/public static RestHighLevelClient putMapping() throws IOException {RestHighLevelClient client = Instance().getClient();PutMappingRequest request = new PutMappingRequest("twitter");pe("_doc");// 我更喜欢Object key-pairs 的形式request.source("message","type=text","name","type=keyword");request.timeout(TimeValue.timeValueMinutes(2));request.masterNodeTimeout(TimeValue.timeValueMinutes(1));AcknowledgedResponse putMappingResponse = client.indices().putMapping(request, RequestOptions.DEFAULT);boolean acknowledged = putMappingResponse.isAcknowledged();System.out.println(acknowledged);return client;}
14.14 Get Mappings
HTTP
# 获取全部索引的Mapping,可以精确到type GET /_all/_mapping/[Type] #获取指定索引的Mapping GET /twitter/_mapping/[Type] # 例如: GET /china_index/_mapping ... {"china_index" : {"mappings" : {"city" : {"properties" : {"cName" : {"type" : "text"},"location" : {"type" : "geo_point"},"pName" : {"type" : "keyword"}}}}} }
Java
/*** 获取mapping* @return* @throws IOException*/public static RestHighLevelClient getMapping() throws IOException {RestHighLevelClient client = Instance().getClient();GetMappingsRequest request = new GetMappingsRequest();request.indices("china_index");pes("city");request.masterNodeTimeout(TimeValue.timeValueMinutes(1));GetMappingsResponse getMappingResponse = client.indices().getMapping(request, RequestOptions.DEFAULT);Mappings().forEach(e -> {String key = e.key;ImmutableOpenMap<String, MappingMetaData> value = e.value;value.forEach(v -> {System.out.println(key + "|" + v.key + "|" + SourceAsMap());});});return client;}
结果:
china_index|city|{properties={pName={type=keyword}, cName={type=text}, location={type=geo_point}}}
14.15 Get Field Mappings
HTTP
# 查看具体字段的Mapping信息 GET [索引]/_mapping/field/[field1,field2] GET china_index/_mapping/field/pName,location .. {"china_index" : {"mappings" : {"city" : {"pName" : {"full_name" : "pName","mapping" : {"pName" : {"type" : "keyword"}}},"location" : {"full_name" : "location","mapping" : {"location" : {"type" : "geo_point"}}}}}} }
Java
/*** 获取指定字段的Mapping* @return* @throws IOException*/public static RestHighLevelClient getFieldMappings() throws IOException {RestHighLevelClient client = Instance().getClient();GetFieldMappingsRequest request = new GetFieldMappingsRequest();request.indices("china_index"); // 可以多个索引pes("city"); // 多个类型request.fields("pName","location"); // 多个字段GetFieldMappingsResponse response = client.indices().getFieldMapping(request, RequestOptions.DEFAULT);Map<String, Map<String, Map<String, GetFieldMappingsResponse.FieldMappingMetaData>>> mappings = response.mappings();mappings.keySet().forEach(e -> {Map<String, Map<String, GetFieldMappingsResponse.FieldMappingMetaData>> mapMap = (e);mapMap.keySet().forEach(i -> {Map<String, GetFieldMappingsResponse.FieldMappingMetaData> metaDataMap = (i);metaDataMap.keySet().forEach(j -> {GetFieldMappingsResponse.FieldMappingMetaData fieldMappingMetaData = (j);System.out.println(e + "|" + i + "|" + j + "|" + fieldMappingMetaData.sourceAsMap());});});});return client;}
结果:
china_index|city|pName|{pName={type=keyword}} china_index|city|location|{location={type=geo_point}}
14.16 Index Aliases
HTTP
# 添加别名 POST /_aliases {"actions" : [{ "remove" : { "index" : "test1", "alias" : "alias1" } },{ "add" : { "index" : "test2", "alias" : "alias1" } }] } # 例子 POST /_aliases {"actions" : [{ "add" : { "index" : "my_source_index", "alias" : "alias111" } },{ "add" : { "index" : "my_source_index2", "alias" : "alias222" } }] } ... {"acknowledged" : true }
Java
/*** 添加别名,这个方法只是列出了一些情况,如果要运行请先根据实际情况修改* @return*/public static RestHighLevelClient indexAlias() throws IOException {RestHighLevelClient client = Instance().getClient();IndicesAliasesRequest request = new IndicesAliasesRequest();IndicesAliasesRequest.AliasActions aliasAction =new IndicesAliasesRequest.AliasActions(IndicesAliasesRequest.AliasActions.Type.ADD).index("index1").alias("alias1");// 添加别名,并指定routingIndicesAliasesRequest.AliasActions addIndicesAction =new IndicesAliasesRequest.AliasActions(IndicesAliasesRequest.AliasActions.Type.ADD).indices("index1", "index2").alias("alias2").routing("my_routing");// 移除别名IndicesAliasesRequest.AliasActions removeAction =new IndicesAliasesRequest.AliasActions(IndicesAliasesRequest.AliasActions.Type.REMOVE).index("index3").alias("alias3");// 删除索引IndicesAliasesRequest.AliasActions removeIndexAction =new IndicesAliasesRequest.AliasActions(IndicesAliasesRequest.AliasActions.Type.REMOVE_INDEX).index("index4");request.addAliasAction(aliasAction);AcknowledgedResponse indicesAliasesResponse =client.indices().updateAliases(request, RequestOptions.DEFAULT);boolean acknowledged = indicesAliasesResponse.isAcknowledged();System.out.println(acknowledged);return client;}
14.17 Exists Alias
HTTP
# 检查 HEAD /my_source_index/_alias/alias111 # 从所有索引里面找别名为2016的 HEAD /_alias/2016 # 还可以使用通配符 HEAD /_alias/20* --- 存在的话 200 - OK 不存在 404 - Not Found
Java
/*** 判断别名是否存在* @return* @throws IOException*/public static RestHighLevelClient aliasExist() throws IOException {RestHighLevelClient client = Instance().getClient();GetAliasesRequest request = new GetAliasesRequest();request.aliases("alias222");request.indices("my_source_index2"); // GetAliasesRequest requestWithAlias = new GetAliasesRequest("alias1"); // 单个 // GetAliasesRequest requestWithAliases = // new GetAliasesRequest(new String[]{"alias1", "alias2"}); // 多个boolean exists = client.indices().existsAlias(request, RequestOptions.DEFAULT);System.out.println(exists);return client;}
结果:true
14.18 Get Alias
HTTP
# 获取 GET /my_source_index/_alias/alias111 -- {"my_source_index" : {"aliases" : {"alias111" : { }}} } # 从所有索引里面找别名为alias222的 GET /_alias/alias222 -- {"my_source_index2" : {"aliases" : {"alias222" : { }}} } # 还可以使用通配符 GET /_alias/20* # 显示索引的所有别名 GET /my_source_index/_alias/* # 所有别名 GET /_alias/* -- {"my_target_index2" : {"aliases" : {"my_search_indices" : { }}},"my_source_index2" : {"aliases" : {"alias222" : { }}},".kibana_1" : {"aliases" : {".kibana" : { }}},"my_source_index" : {"aliases" : {"alias111" : { }}},"my_target_index" : {"aliases" : {"my_search_indices" : { }}} }
如果要删除
# 删除别名 DELETE /my_source_index/_alias/alias111 -- {"acknowledged" : true }
Java
/*** 获取别名* @return* @throws IOException*/public static RestHighLevelClient getAlias() throws IOException {RestHighLevelClient client = Instance().getClient();GetAliasesRequest request = new GetAliasesRequest();request.aliases("alias222");request.indices("my_source_index2"); // GetAliasesRequest requestWithAlias = new GetAliasesRequest("alias1"); // GetAliasesRequest requestWithAliases = // new GetAliasesRequest(new String[]{"alias1", "alias2"});GetAliasesResponse response = client.indices().getAlias(request, RequestOptions.DEFAULT);Map<String, Set<AliasMetaData>> aliases = Aliases();aliases.keySet().forEach(e -> {Set<AliasMetaData> aliasMetaData = (e);System.out.println(e + ":" + String());});return client;}
结果:
my_source_index2:[{"alias222" : { } }]
14.19 Update Indices Settings
HTTP
# 更新setting PUT /twitter/_settings {"index" : {"number_of_replicas" : 2,"refresh_interval" : "1s"} }
Java
/*** 更新setting* @return* @throws IOException*/public static RestHighLevelClient updateSetting() throws IOException {RestHighLevelClient client = Instance().getClient();// 更新单个UpdateSettingsRequest request = new UpdateSettingsRequest("index1");// 更新多个//UpdateSettingsRequest requestMultiple =// new UpdateSettingsRequest("index1", "index2");// 全部更新//UpdateSettingsRequest requestAll = new UpdateSettingsRequest();Settings settings =Settings.builder().put("index.number_of_replicas", 2).build();request.settings(settings);AcknowledgedResponse updateSettingsResponse =client.indices().putSettings(request, RequestOptions.DEFAULT);boolean acknowledged = updateSettingsResponse.isAcknowledged();System.out.println(acknowledged);return client;}
14.20 Get Settings
HTTP
# 获取指定索引的settings GET /twitter,kimchy/_settings # 获取全部settings GET /_all/_settings
Java
/*** 获取setting* @return* @throws IOException*/public static RestHighLevelClient getSetting() throws IOException {RestHighLevelClient client = Instance().getClient();GetSettingsRequest request = new GetSettingsRequest().indices("china_index");GetSettingsResponse getSettingsResponse = client.indices().getSettings(request, RequestOptions.DEFAULT);ImmutableOpenMap<String, Settings> settings = IndexToSettings();settings.forEach(e -> {System.out.println(e.key);Settings value = e.value;value.keySet().forEach(k -> {System.out.println(k + ":" + (k));});});return client;}
结果:
china_index ation_date:1545294776325 index.number_of_replicas:1 index.number_of_shards:1 index.provided_name:china_index index.uuid:LYn6XQ_sRZCazMtweW31ZA ated:6050099
14.21 Put Template & Get Templates
# 索引模板 PUT _template/template_1 {"index_patterns": ["te*", "bar*"],"settings": {"number_of_shards": 1},"mappings": {"my_doc": {"_source": {"enabled": false},"properties": {"host_name": {"type": "keyword"},"created_at": {"type": "date","format": "EEE MMM dd HH:mm:ss Z YYYY"}}}} } # 删除模板 DELETE /_template/template_1 # 获取模板 GET /_template/template_1 # 获取所有模板 GET /_template # 模板是否存在 HEAD _template/template_1
14.22 Validate Query
public static RestHighLevelClient validateQuery() throws IOException {RestHighLevelClient client = Instance().getClient();// ValidateQueryRequest需要一个或多个索引来验证查询。如果没有提供索引,则在所有索引上执行请求。ValidateQueryRequest request = new ValidateQueryRequest("twitter");QueryBuilder builder = QueryBuilders.boolQuery().must(QueryBuilders.queryStringQuery("*:*")).Query("user", "kimchy"));request.query(builder);request.allShards(true);// 默认情况下,请求只在一个随机选择的分片上执行plain(true);write(true);ValidateQueryResponse response = client.indices().validateQuery(request, RequestOptions.DEFAULT);boolean isValid = response.isValid();int totalShards = TotalShards();int successfulShards = SuccessfulShards();int failedShards = FailedShards();System.out.println("isValid:" + isValid + ",totalShards:" + totalShards + ",successfulShards:" + successfulShards + ",failedShards:" + failedShards);if (failedShards > 0) {for(DefaultShardOperationFailedException failure: ShardFailures()) {String failedIndex = failure.index();int shardId = failure.shardId();String reason = ason();System.out.println("failedIndex:" + failedIndex + ",shardId:" + shardId + ",reason:" + reason);}}for(QueryExplanation explanation: QueryExplanation()) {String explanationIndex = Index();int shardId = Shard();String explanationString = Explanation();System.out.println("explanationIndex:" + explanationIndex + ",shardId:" + shardId + ",explanationString:" + explanationString);}return client;}
结果:
isValid:true,totalShards:5,successfulShards:5,failedShards:0 explanationIndex:twitter,shardId:0,explanationString:ConstantScore(user:kimchy) explanationIndex:twitter,shardId:1,explanationString:ConstantScore(user:kimchy) explanationIndex:twitter,shardId:2,explanationString:ConstantScore(user:kimchy) explanationIndex:twitter,shardId:3,explanationString:ConstantScore(user:kimchy) explanationIndex:twitter,shardId:4,explanationString:ConstantScore(user:kimchy)
14.23 Get Index
HTTP
# 获取所有索引信息 GET /_all # 单个索引信息 GET /twitter
Java
/*** 获取索引详细信息* @return* @throws IOException*/public static RestHighLevelClient getIndex() throws IOException {RestHighLevelClient client = Instance().getClient();GetIndexRequest request = new GetIndexRequest().indices("_all"); // _all是关键字,列出所有索引信息。也可以是通配符*GetIndexResponse indexResponse = client.indices().get(request, RequestOptions.DEFAULT);// MappingsImmutableOpenMap<String, ImmutableOpenMap<String, MappingMetaData>> mappings = Mappings();mappings.forEach(e -> {String key = e.key;ImmutableOpenMap<String, MappingMetaData> map = e.value;System.out.println("Index:" + key);map.forEach(n -> {String type = n.key;MappingMetaData metaData = n.value;System.out.println(type + "|" + SourceAsMap());});});// AliasesSystem.out.println("**********************************");ImmutableOpenMap<String, List<AliasMetaData>> aliases = Aliases();aliases.forEach(e -> {String key = e.key;List<AliasMetaData> value = e.value;System.out.println("----" + key + "----");value.forEach(a -> {System.out.println(a.alias());});});// SettingsSystem.out.println("**********************************");ImmutableOpenMap<String, Settings> defaultSettings = indexResponse.defaultSettings();defaultSettings.forEach(e -> {String key = e.key;Settings value = e.value;System.out.println("----" + key + "----");value.keySet().forEach(k -> {System.out.println(k + ":" + (k));});});ImmutableOpenMap<String, Settings> settings = Settings();settings.forEach(e -> {String key = e.key;Settings value = e.value;System.out.println("----" + key + "----");value.keySet().forEach(k -> {System.out.println(k + ":" + (k));});});return client;}
结果:
Index:china_shape_index info|{properties={location={precision=100.0m, type=geo_shape}, remark={type=keyword}}} Index:china_index city|{properties={pName={type=keyword}, cName={type=text}, location={type=geo_point}}} Index:books java|{properties={title={type=text, fields={keyword={ignore_above=256, type=keyword}}}, user={type=text, fields={keyword={ignore_above=256, type=keyword}}}}} Index:my_source_index2 Index:my_target_index2 Index:my_source_index Index:users info|{properties={address={analyzer=ik_max_word, type=text}, age={type=long}, username={type=keyword}}} Index:my_target_index Index:test msg|{properties={message={analyzer=ik_max_word, type=text}}} Index:.kibana_1 doc|{dynamic=strict, properties={server={properties={uuid={type=keyword}}}, visualization={properties={savedSearchId={type=keyword}, description={type=text}, uiStateJSON={type=text}, title={type=text}, version={type=integer}, kibanaSavedObjectMeta={properties={searchSourceJSON={type=text}}}, visState={type=text}}}, graph-workspace={properties={numVertices={type=integer}, description={type=text}, numLinks={type=integer}, title={type=text}, version={type=integer}, kibanaSavedObjectMeta={properties={searchSourceJSON={type=text}}}, wsState={type=text}}}, kql-telemetry={properties={optInCount={type=long}, optOutCount={type=long}}}, type={type=keyword}, space={properties={color={type=keyword}, _reserved={type=boolean}, initials={type=keyword}, name={type=text, fields={keyword={ignore_above=2048, type=keyword}}}, description={type=text}}}, url={properties={accessCount={type=long}, accessDate={type=date}, url={type=text, fields={keyword={ignore_above=2048, type=keyword}}}, createDate={type=date}}}, migrationVersion={dynamic=true, type=object}, index-pattern={properties={notExpandable={type=boolean}, fieldFormatMap={type=text}, sourceFilters={type=text}, typeMeta={type=keyword}, timeFieldName={type=keyword}, intervalName={type=keyword}, fields={type=text}, title={type=text}, type={type=keyword}}}, search={properties={hits={type=integer}, columns={type=keyword}, description={type=text}, sort={type=keyword}, title={type=text}, version={type=integer}, kibanaSavedObjectMeta={properties={searchSourceJSON={type=text}}}}}, updated_at={type=date}, canvas-workpad={dynamic=false, properties={@created={type=date}, @timestamp={type=date}, name={type=text, fields={keyword={type=keyword}}}, id={index=false, type=text}}}, namespace={type=keyword}, telemetry={properties={enabled={type=boolean}}}, timelion-sheet={properties={hits={type=integer}, timelion_sheet={type=text}, timelion_interval={type=keyword}, timelion_columns={type=integer}, timelion_other_interval={type=keyword}, timelion_rows={type=integer}, description={type=text}, title={type=text}, version={type=integer}, kibanaSavedObjectMeta={properties={searchSourceJSON={type=text}}}, timelion_chart_height={type=integer}}}, config={dynamic=true, properties={buildNum={type=keyword}}}, dashboard={properties={hits={type=integer}, timeFrom={type=keyword}, timeTo={type=keyword}, refreshInterval={properties={display={type=keyword}, section={type=integer}, value={type=integer}, pause={type=boolean}}}, description={type=text}, uiStateJSON={type=text}, timeRestore={type=boolean}, title={type=text}, version={type=integer}, kibanaSavedObjectMeta={properties={searchSourceJSON={type=text}}}, optionsJSON={type=text}, panelsJSON={type=text}}}}} Index:twitter t_doc|{properties={msg={type=text, fields={keyword={ignore_above=256, type=keyword}}}, A={type=text, fields={keyword={ignore_above=256, type=keyword}}}, B={type=text, fields={keyword={ignore_above=256, type=keyword}}}, C={type=text, fields={keyword={ignore_above=256, type=keyword}}}, flag={type=text, fields={keyword={ignore_above=256, type=keyword}}}, D={type=text, fields={keyword={ignore_above=256, type=keyword}}}, color={type=text, fields={keyword={ignore_above=256, type=keyword}}}, updateUser={type=text, fields={keyword={ignore_above=256, type=keyword}}}, extMsg={type=text, fields={keyword={ignore_above=256, type=keyword}}}, counter={type=long}, message={type=text, fields={keyword={ignore_above=256, type=keyword}}}, field={type=text, fields={keyword={ignore_above=256, type=keyword}}}, size={type=text, fields={keyword={ignore_above=256, type=keyword}}}, post_date={type=date}, name={type=text, fields={keyword={ignore_above=256, type=keyword}}}, animal={properties={cat={type=text, fields={keyword={ignore_above=256, type=keyword}}}, dog={type=text, fields={keyword={ignore_above=256, type=keyword}}}}}, postDate={type=date}, hate={type=text, fields={keyword={ignore_above=256, type=keyword}}}, favorite={type=text, fields={keyword={ignore_above=256, type=keyword}}}, user={type=text, fields={keyword={ignore_above=256, type=keyword}}}}} ********************************** ----china_shape_index---- ----.kibana_1---- .kibana ----china_index---- ----users---- ----my_source_index---- ----my_source_index2---- alias222 ----my_target_index2---- my_search_indices ----my_target_index---- my_search_indices ----test---- ----twitter---- ----books---- ********************************** ----my_target_index---- index.allocation.max_retries:1 index.blocks.write:true dec:best_compression ation_date:1546589354014 index.number_of_replicas:1 index.number_of_shards:1 index.provided_name:my_target_index size.source.name:my_source_index size.source.uuid:tSYNLldWQNCOlR5NJGaH9g uting.allocation.initial_recovery._id:wCr6Uz0jTvGaTHh5acNxKA uting_partition_size:1 index.shrink.source.name:my_source_index index.shrink.source.uuid:tSYNLldWQNCOlR5NJGaH9g index.uuid:F976xviGQ965JU9patwQnA ated:6050099 index.version.upgraded:6050099 ----twitter---- ation_date:1545622508123 index.number_of_replicas:1 index.number_of_shards:5 index.provided_name:twitter index.uuid:TLReCXTSSe6tvI7yNveWgw ated:6050099 ----books---- ation_date:1545708244767 index.number_of_replicas:1 index.number_of_shards:5 index.provided_name:books index.uuid:leQWEGe8So6B10awTItCNg ated:6050099 ----users---- ation_date:1545967628013 index.number_of_replicas:1 index.number_of_shards:1 index.provided_name:users index.uuid:tyxNGtSsThOFDaTBBy7jKQ ated:6050099 ----my_source_index---- index.blocks.write:true ation_date:1546589291669 index.number_of_replicas:2 index.number_of_shards:4 index.provided_name:my_source_index index.uuid:tSYNLldWQNCOlR5NJGaH9g ated:6050099 ----my_source_index2---- index.blocks.write:true ation_date:1546590226265 index.number_of_replicas:1 index.number_of_shards:2 index.provided_name:my_source_index2 index.uuid:iuDENl3uQku0Ef6flu8S-Q ated:6050099 ----test---- ation_date:1545791918478 index.number_of_replicas:1 index.number_of_shards:1 index.provided_name:test index.uuid:qF3UiIqHTLK_X7FSUUhlGw ated:6050099 ----china_shape_index---- ation_date:1545981755548 index.number_of_replicas:1 index.number_of_shards:1 index.provided_name:china_shape_index index.uuid:jhwyVqR0RQywyf3n7W0maQ ated:6050099 ----china_index---- ation_date:1545294776325 index.number_of_replicas:1 index.number_of_shards:1 index.provided_name:china_index index.uuid:LYn6XQ_sRZCazMtweW31ZA ated:6050099 ----.kibana_1---- index.auto_expand_replicas:0-1 ation_date:1542353618696 index.number_of_replicas:0 index.number_of_shards:1 index.provided_name:.kibana_1 index.uuid:IvzG6JhgRJ-GgwTDWmmirQ ated:6050099 ----my_target_index2---- index.blocks.write:true ation_date:1546590255143 index.number_of_replicas:1 index.number_of_shards:4 index.provided_name:my_target_index2 size.source.name:my_source_index2 size.source.uuid:iuDENl3uQku0Ef6flu8S-Q uting_partition_size:1 index.uuid:ZBnocs2bSker45kb2lXoRw ated:6050099 index.version.upgraded:6050099Process finished with exit code 0
完
转载于:.html
本文发布于:2024-01-29 01:10:26,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170646183311635.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |