简单研究下Java High Level REST Client 的使用方法。这个Client连接的端口是ES的HTTP端口。
参考:https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high.html
0.pom
<dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>elasticsearch-rest-high-level-client</artifactId> <version>7.8.1</version> </dependency>
启动两个ES服务:
elasticsearch.bat -Ehttp.port=9200 -Epath.data=E:/data/0 elasticsearch.bat -Ehttp.port=19200 -Epath.data=E:/data/1
1.Index相关API
0.获取所有的Index
private static void getAllIndex() throws IOException { // on startup RestHighLevelClient client = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http"), new HttpHost("localhost", 19200, "http"))); try { GetAliasesRequest request = new GetAliasesRequest(); GetAliasesResponse getAliasesResponse = client.indices().getAlias(request, RequestOptions.DEFAULT); Map<String, Set<AliasMetadata>> aliases = getAliasesResponse.getAliases(); Set<String> indices = aliases.keySet(); for (String key : indices) { System.out.println(key); } } catch (IOException e) { e.printStackTrace(); } // on shutdown client.close(); }
结果:
test
.kibana_task_manager_1
.apm-agent-configuration
accounts
.kibana_1
users
1.创建Index
private static void creareIndex() throws IOException { // on startup RestHighLevelClient client = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http"), new HttpHost("localhost", 19200, "http"))); CreateIndexRequest request = new CreateIndexRequest("test"); // 设置分片数量和副本数量 request.settings(Settings.builder().put("index.number_of_shards", 3).put("index.number_of_replicas", 2)); // 字段映射 Map<String, Object> message = new HashMap<>(); message.put("type", "text"); Map<String, Object> properties = new HashMap<>(); properties.put("message", message); Map<String, Object> mapping = new HashMap<>(); mapping.put("properties", properties); request.mapping(mapping); // 执行创建请求 CreateIndexResponse createIndexResponse = client.indices().create(request, RequestOptions.DEFAULT); boolean acknowledged = createIndexResponse.isAcknowledged(); boolean shardsAcknowledged = createIndexResponse.isShardsAcknowledged(); System.out.println(acknowledged && shardsAcknowledged); // on shutdown client.close(); }
2. 判断是否存在
private static void exists() throws IOException { // on startup RestHighLevelClient client = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http"), new HttpHost("localhost", 19200, "http"))); GetIndexRequest request = new GetIndexRequest("test"); boolean exists = client.indices().exists(request, RequestOptions.DEFAULT); System.out.println(exists); // on shutdown client.close(); }
3.获取Index的分片数量和副本数量
private static void GetIndexRequest() throws IOException { // on startup RestHighLevelClient client = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http"), new HttpHost("localhost", 19200, "http"))); GetSettingsRequest request = new GetSettingsRequest().indices("test"); GetSettingsResponse getSettingsResponse = client.indices().getSettings(request, RequestOptions.DEFAULT); String numberOfShardsString = getSettingsResponse.getSetting("test", "index.number_of_shards"); System.out.println(numberOfShardsString); Settings indexSettings = getSettingsResponse.getIndexToSettings().get("test"); Integer numberOfShards = indexSettings.getAsInt("index.number_of_shards", null); System.out.println(numberOfShards); // on shutdown client.close(); }
4.获取Mapping
private static void getMapping() throws IOException { // on startup RestHighLevelClient client = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http"), new HttpHost("localhost", 19200, "http"))); GetMappingsRequest request = new GetMappingsRequest(); request.indices("test"); GetMappingsResponse getMappingResponse = client.indices().getMapping(request, RequestOptions.DEFAULT); Map<String, MappingMetadata> allMappings = getMappingResponse.mappings(); MappingMetadata indexMapping = allMappings.get("test"); Map<String, Object> mapping = indexMapping.sourceAsMap(); System.out.println(mapping); // on shutdown client.close(); }
结果:
{properties={message={type=text}}}
5.修改Mapping
private static void putMapping() throws IOException { // on startup RestHighLevelClient client = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http"), new HttpHost("localhost", 19200, "http"))); PutMappingRequest request = new PutMappingRequest("test"); Map<String, Object> jsonMap = new HashMap<>(); Map<String, Object> message = new HashMap<>(); message.put("type", "text"); Map<String, Object> properties = new HashMap<>(); properties.put("message", message); jsonMap.put("properties", properties); request.source(jsonMap); AcknowledgedResponse putMappingResponse = client.indices().putMapping(request, RequestOptions.DEFAULT); boolean acknowledged = putMappingResponse.isAcknowledged(); System.out.println(acknowledged); // on shutdown client.close(); }
6.删除Index
private static void delete() throws IOException { // on startup RestHighLevelClient client = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http"), new HttpHost("localhost", 19200, "http"))); try { // 索引不存在抛出ElasticsearchException异常 DeleteIndexRequest request = new DeleteIndexRequest("does_not_exist"); AcknowledgedResponse delete = client.indices().delete(request, RequestOptions.DEFAULT); boolean acknowledged = delete.isAcknowledged(); System.out.println(acknowledged); } catch (ElasticsearchException exception) { if (exception.status() == RestStatus.NOT_FOUND) { } } // on shutdown client.close(); }
补充: 上面的操作都有异步操作,例如
private static void delete() throws IOException, InterruptedException { CountDownLatch countDownLatch = new CountDownLatch(1); // on startup RestHighLevelClient client = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http"), new HttpHost("localhost", 19200, "http"))); try { // 索引不存在抛出ElasticsearchException异常 DeleteIndexRequest request = new DeleteIndexRequest("test"); ActionListener<AcknowledgedResponse> listener = new ActionListener<AcknowledgedResponse>() { @Override public void onResponse(AcknowledgedResponse deleteIndexResponse) { System.out.println("1"); System.out.println(deleteIndexResponse.isAcknowledged()); countDownLatch.countDown(); } @Override public void onFailure(Exception e) { System.out.println("2"); e.printStackTrace(); countDownLatch.countDown(); } }; client.indices().deleteAsync(request, RequestOptions.DEFAULT, listener); } catch (ElasticsearchException exception) { if (exception.status() == RestStatus.NOT_FOUND) { System.out.println("3"); exception.printStackTrace(); countDownLatch.countDown(); } } countDownLatch.await(); // on shutdown client.close(); }
上面是异步操作的方法,增加listener监听器。加CountDownLatch进行await是为了进行测试效果。实际中不应该使用闭锁。
2.Document APIs
0.准备Index-news 使用IK分词器(关于ES整合IK分词器参考之前的)
private static void createIndex() throws IOException { // on startup RestHighLevelClient client = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http"), new HttpHost("localhost", 19200, "http"))); CreateIndexRequest request = new CreateIndexRequest("news"); // 设置分片数量和副本数量 request.settings(Settings.builder().put("index.number_of_shards", 3).put("index.number_of_replicas", 2)); // 字段映射 Map<String, Object> properties = new HashMap<>(); properties.put("id", getField("long")); properties.put("type", getField("keyword")); properties.put("title", getField("text")); properties.put("content", getField("text")); properties.put("creator", getField("keyword")); properties.put("createTime", getField("date")); Map<String, Object> mapping = new HashMap<>(); mapping.put("properties", properties); request.mapping(mapping); // 执行创建请求 CreateIndexResponse createIndexResponse = client.indices().create(request, RequestOptions.DEFAULT); boolean acknowledged = createIndexResponse.isAcknowledged(); boolean shardsAcknowledged = createIndexResponse.isShardsAcknowledged(); System.out.println(acknowledged && shardsAcknowledged); // on shutdown client.close(); } private static Map<String, Object> getField(String type) { Map<String, Object> result = new HashMap<>(); result.put("type", type); if ("text".equals(type)) { result.put("analyzer", "ik_max_word"); result.put("search_analyzer", "ik_smart"); } return result; }
查看字段映射如下:
{properties={creator={type=keyword}, createTime={type=date}, id={type=long}, title={search_analyzer=ik_smart, analyzer=ik_max_word, type=text}, type={type=keyword}, content={search_analyzer=ik_smart, analyzer=ik_max_word, type=text}}}
1.创建索引
private static void createDoc() throws IOException { // on startup RestHighLevelClient client = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http"), new HttpHost("localhost", 19200, "http"))); String[] type = { "杂文", "java", "vue", "js", "es" }; String[] title = { "杂文记录", "java记录", "vue记录", "js记录", "js记录" }; String[] content = { "这里是杂文记录", "这里是java记录", "这里是vue记录", "这里是js记录", "这里是js记录" }; Map<String, Object> jsonMap = new HashMap<>(); for (int i = 0; i < 9; i++) { jsonMap.clear(); int indexNum = i % 5; jsonMap.put("type", type[indexNum]); jsonMap.put("title", title[indexNum]); jsonMap.put("content", content[indexNum]); jsonMap.put("creator", "creator" + i); jsonMap.put("createTime", new Date()); IndexRequest indexRequest = new IndexRequest("news").source(jsonMap); IndexResponse response = client.index(indexRequest, RequestOptions.DEFAULT); System.out.println("=============" + i); // 打印保存信息 // Index name String _index = response.getIndex(); System.out.println("_index " + _index); // Type name String _type = response.getType(); System.out.println("_type " + _type); // Document ID (generated or not) String _id = response.getId(); System.out.println("_id " + _id); // Version (if it's the first time you index this document, you will // get: 1) long _version = response.getVersion(); System.out.println("_version " + _version); // status has stored current instance statement. RestStatus status = response.status(); System.out.println("status " + status); } // on shutdown client.close(); }
结果:
=============0
_index news
_type _doc
_id -Z4LB3QBhQI7S8XqvLjl
_version 1
status CREATED
=============1
_index news
_type _doc
_id NAILB3QBfZgDx-b1xOMr
_version 1
status CREATED
=============2
_index news
_type _doc
_id -p4LB3QBhQI7S8Xqx7ix
_version 1
status CREATED
=============3
_index news
_type _doc
_id NQILB3QBfZgDx-b1yeNE
_version 1
status CREATED
=============4
_index news
_type _doc
_id -54LB3QBhQI7S8Xqyrjs
_version 1
status CREATED
=============5
_index news
_type _doc
_id NgILB3QBfZgDx-b1zOMK
_version 1
status CREATED
=============6
_index news
_type _doc
_id _J4LB3QBhQI7S8XqzLjT
_version 1
status CREATED
=============7
_index news
_type _doc
_id NwILB3QBfZgDx-b1zeN9
_version 1
status CREATED
=============8
_index news
_type _doc
_id _Z4LB3QBhQI7S8Xqzrhk
_version 1
status CREATED
补充:上面的方式不会给ID赋值,ID是ES自动生成的,如果需要自己赋值,如下:
IndexRequest indexRequest = new IndexRequest("news").id((i + 1) + "").source(jsonMap);
2. Get API 根据ID查询
根据ID查询
private static void getDoc() throws IOException { String defaultIndex = "news"; // on startup RestHighLevelClient client = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http"), new HttpHost("localhost", 19200, "http"))); GetRequest getRequest = new GetRequest(defaultIndex, "1"); GetResponse getResponse = client.get(getRequest, RequestOptions.DEFAULT); String index = getResponse.getIndex(); String id = getResponse.getId(); if (getResponse.isExists()) { long version = getResponse.getVersion(); String sourceAsString = getResponse.getSourceAsString(); Map<String, Object> sourceAsMap = getResponse.getSourceAsMap(); System.out.println(index); System.out.println(id); System.out.println(version); System.out.println(sourceAsString); System.out.println(sourceAsMap); } else { System.out.println("不存在"); } // on shutdown client.close(); }
结果:
news
1
1
{"creator":"creator0","createTime":"2020-08-19T14:17:18.790Z","type":"杂文","title":"杂文记录","content":"这里是杂文记录"}
{creator=creator0, createTime=2020-08-19T14:17:18.790Z, type=杂文, title=杂文记录, content=这里是杂文记录}
3.Get Source 获取数据内容
private static void getSource() throws IOException { String defaultIndex = "news"; // on startup RestHighLevelClient client = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http"), new HttpHost("localhost", 19200, "http"))); GetSourceRequest getSourceRequest = new GetSourceRequest(defaultIndex, "1"); GetSourceResponse response = client.getSource(getSourceRequest, RequestOptions.DEFAULT); Map<String, Object> source = response.getSource(); System.out.println(source); // on shutdown client.close(); }
结果:
{creator=creator0, createTime=2020-08-19T14:17:18.790Z, type=杂文, title=杂文记录, content=这里是杂文记录}
4. exists 判断存在
private static void exists() throws IOException { String defaultIndex = "news"; // on startup RestHighLevelClient client = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http"), new HttpHost("localhost", 19200, "http"))); GetRequest getRequest = new GetRequest(defaultIndex, "1"); // Disable fetching _source. getRequest.fetchSourceContext(new FetchSourceContext(false)); // Disable fetching stored fields. getRequest.storedFields("_none_"); boolean exists = client.exists(getRequest, RequestOptions.DEFAULT); System.out.println(exists); // on shutdown client.close(); }
结果:
true
5.Delete 根据ID删除
private static void delete() throws IOException { String defaultIndex = "news"; // on startup RestHighLevelClient client = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http"), new HttpHost("localhost", 19200, "http"))); DeleteRequest request = new DeleteRequest(defaultIndex, "1"); DeleteResponse deleteResponse = client.delete(request, RequestOptions.DEFAULT); String index = deleteResponse.getIndex(); String id = deleteResponse.getId(); System.out.println(index + " " + id); // on shutdown client.close(); }
结果:
news 1
6. Update根据ID修改
private static void update() throws IOException { String defaultIndex = "news"; // on startup RestHighLevelClient client = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http"), new HttpHost("localhost", 19200, "http"))); // 修改部分字段 Map<String, Object> jsonMap = new HashMap<>(); jsonMap.put("content", "修改过的"); UpdateRequest request = new UpdateRequest(defaultIndex, "1").doc(jsonMap); // 修改完读取数据 request.fetchSource(true); // 执行修改 UpdateResponse updateResponse = client.update(request, RequestOptions.DEFAULT); GetResult result = updateResponse.getGetResult(); if (result.isExists()) { Map<String, Object> sourceAsMap = result.sourceAsMap(); System.out.println(sourceAsMap); } else { } // on shutdown client.close(); }
结果:
{creator=creator0, createTime=2020-08-19T14:32:37.804Z, type=杂文, title=杂文记录, content=修改过的}
补充: 用脚本更新
private static void update() throws IOException { String defaultIndex = "news"; // on startup RestHighLevelClient client = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http"), new HttpHost("localhost", 19200, "http"))); // 多个请求.可以是相同的增加请求也可以是不同类型的请求 UpdateRequest request = new UpdateRequest(defaultIndex, "1"); // 修改完读取数据 request.fetchSource(true); // 添加请求 Map<String, Object> singletonMap = new HashMap<>(); singletonMap.put("content", "append"); Script inline = new Script(ScriptType.INLINE, "painless", "ctx._source.content += params.content", singletonMap); request.script(inline); UpdateResponse updateResponse = client.update(request, RequestOptions.DEFAULT); GetResult result = updateResponse.getGetResult(); if (result.isExists()) { Map<String, Object> sourceAsMap = result.sourceAsMap(); System.out.println(sourceAsMap); } else { } // on shutdown client.close(); }
结果:
{creator=creator0, field=nullappend, createTime=2020-08-19T14:32:37.804Z, type=杂文, title=杂文记录, content=java NP!!!!append}
6.termVector
待补充
7. bulk API 在一次请求中发送多个ES请求(增删改等)
private static void bulk() throws IOException { String defaultIndex = "news"; // on startup RestHighLevelClient client = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http"), new HttpHost("localhost", 19200, "http"))); // 多个请求.可以是相同的增加请求也可以是不同类型的请求 BulkRequest request = new BulkRequest(); // 添加请求 Map<String, Object> jsonMap = new HashMap<>(); jsonMap.put("type", "java"); jsonMap.put("content", "java NP"); jsonMap.put("creator", "creator2"); jsonMap.put("createTime", new Date()); request.add(new IndexRequest(defaultIndex).id("2").source(jsonMap)); // 修改请求 Map<String, Object> jsonMap2 = new HashMap<>(); jsonMap2.put("content", "java NP!!!!"); request.add(new UpdateRequest(defaultIndex, "1").doc(jsonMap2)); BulkResponse bulkResponse = client.bulk(request, RequestOptions.DEFAULT); for (BulkItemResponse bulkItemResponse : bulkResponse) { DocWriteResponse itemResponse = bulkItemResponse.getResponse(); switch (bulkItemResponse.getOpType()) { case INDEX: case CREATE: IndexResponse indexResponse = (IndexResponse) itemResponse; System.out.println("create " + indexResponse); break; case UPDATE: UpdateResponse updateResponse = (UpdateResponse) itemResponse; System.out.println("updateResponse " + updateResponse); break; case DELETE: DeleteResponse deleteResponse = (DeleteResponse) itemResponse; } } // on shutdown client.close(); }
结果:
create IndexResponse[index=news,type=_doc,id=2,version=1,result=created,seqNo=2,primaryTerm=1,shards={"total":3,"successful":1,"failed":0}]
updateResponse UpdateResponse[index=news,type=_doc,id=1,version=3,seqNo=9,primaryTerm=1,result=updated,shards=ShardInfo{total=3, successful=1, failures=[]}]
8. multip-get api
private static void multiGet() throws IOException { String defaultIndex = "news"; // on startup RestHighLevelClient client = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http"), new HttpHost("localhost", 19200, "http"))); MultiGetRequest request = new MultiGetRequest(); request.add(new MultiGetRequest.Item(defaultIndex, "1")); request.add(new MultiGetRequest.Item(defaultIndex, "_J4LB3QBhQI7S8XqzLjT")); MultiGetResponse response = client.mget(request, RequestOptions.DEFAULT); MultiGetItemResponse[] responses = response.getResponses(); if (responses != null) { for (MultiGetItemResponse responseTmp : responses) { GetResponse response2 = responseTmp.getResponse(); String index = responseTmp.getIndex(); String id = responseTmp.getId(); if (response2.isExists()) { long version = response2.getVersion(); Map<String, Object> sourceAsMap = response2.getSourceAsMap(); System.out.println(sourceAsMap); } else { } } } // on shutdown client.close(); }
结果:
{creator=creator0, field=nullappend, createTime=2020-08-19T14:32:37.804Z, type=杂文, title=杂文记录, content=java NP!!!!append}
{creator=creator6, createTime=2020-08-19T14:07:27.946Z, type=java, title=java记录, content=这里是java记录}
9.Reindex API
A ReindexRequest can be used to copy documents from one or more indexes into a destination index.
private static void reIndex() throws IOException { String defaultIndex = "news"; // on startup RestHighLevelClient client = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http"), new HttpHost("localhost", 19200, "http"))); ReindexRequest request = new ReindexRequest(); request.setSourceIndices(defaultIndex); request.setDestIndex("news2"); request.setDestOpType("create"); request.setConflicts("proceed"); BulkByScrollResponse bulkResponse = client.reindex(request, RequestOptions.DEFAULT); TimeValue timeTaken = bulkResponse.getTook(); boolean timedOut = bulkResponse.isTimedOut(); long totalDocs = bulkResponse.getTotal(); long updatedDocs = bulkResponse.getUpdated(); long createdDocs = bulkResponse.getCreated(); long deletedDocs = bulkResponse.getDeleted(); long batches = bulkResponse.getBatches(); long noops = bulkResponse.getNoops(); long versionConflicts = bulkResponse.getVersionConflicts(); long bulkRetries = bulkResponse.getBulkRetries(); long searchRetries = bulkResponse.getSearchRetries(); TimeValue throttledMillis = bulkResponse.getStatus().getThrottled(); TimeValue throttledUntilMillis = bulkResponse.getStatus().getThrottledUntil(); List<ScrollableHitSource.SearchFailure> searchFailures = bulkResponse.getSearchFailures(); List<BulkItemResponse.Failure> bulkFailures = bulkResponse.getBulkFailures(); System.out.println(totalDocs); System.out.println(createdDocs); // on shutdown client.close(); }
结果:
11
11
10. UpdateByQuery
private static void reIndex() throws IOException { String defaultIndex = "news"; // on startup RestHighLevelClient client = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http"), new HttpHost("localhost", 19200, "http"))); UpdateByQueryRequest request = new UpdateByQueryRequest(defaultIndex); // request.setQuery(new TermQueryBuilder("creator", "creator0")); request.setScript(new Script(ScriptType.INLINE, "painless", "if (ctx._source.creator == 'creator0') {ctx._source.content='修改后的XXXXXXXX';}", Collections.emptyMap())); // on shutdown client.close(); }
11. DeleteByQuery
private static void deleteByQuery() throws IOException { String defaultIndex = "news"; // on startup RestHighLevelClient client = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http"), new HttpHost("localhost", 19200, "http"))); DeleteByQueryRequest request = new DeleteByQueryRequest(defaultIndex); request.setQuery(new TermQueryBuilder("creator", "creator2")); BulkByScrollResponse bulkResponse = client.deleteByQuery(request, RequestOptions.DEFAULT); // on shutdown client.close(); }
3.Search APIs
1. 查询
1. 查所有:
private static void search() throws IOException { String defaultIndex = "news"; // on startup RestHighLevelClient client = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http"), new HttpHost("localhost", 19200, "http"))); // 创建SearchRequest,可以指定Index,也可以不指定。不指定查询所有 SearchRequest searchRequest = new SearchRequest(defaultIndex); // SearchRequest searchRequest = new SearchRequest(defaultIndex); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); searchSourceBuilder.query(QueryBuilders.matchAllQuery()); searchRequest.source(searchSourceBuilder); SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT); SearchHits hits = searchResponse.getHits(); TotalHits totalHits = hits.getTotalHits(); // the total number of hits, must be interpreted in the context of // totalHits.relation long numHits = totalHits.value; System.out.println("numHits " + numHits); // whether the number of hits is accurate (EQUAL_TO) or a lower bound of // the total (GREATER_THAN_OR_EQUAL_TO) TotalHits.Relation relation = totalHits.relation; float maxScore = hits.getMaxScore(); System.out.println("maxScore " + maxScore); SearchHit[] searchHits = hits.getHits(); for (SearchHit hit : searchHits) { // do something with the SearchHit String sourceAsString = hit.getSourceAsString(); Map<String, Object> sourceAsMap = hit.getSourceAsMap(); System.out.println(sourceAsMap); } // on shutdown client.close(); }
结果:
numHits 9
maxScore 1.0
{creator=creator5, createTime=2020-08-19T14:07:27.745Z, type=杂文, title=杂文记录, content=这里是杂文记录}
{creator=creator8, createTime=2020-08-19T14:07:28.346Z, type=js, title=js记录, content=这里是js记录}
{creator=creator4, createTime=2020-08-19T14:07:27.459Z, type=es, title=js记录, content=这里是js记录}
{creator=creator0, createTime=2020-08-19T14:07:21.696Z, type=杂文, title=杂文记录, content=修改后的XXXXXXXX}
{creator=creator1, createTime=2020-08-19T14:07:25.469Z, type=java, title=java记录, content=这里是java记录}
{creator=creator3, createTime=2020-08-19T14:07:27.034Z, type=js, title=js记录, content=这里是js记录}
{creator=creator6, createTime=2020-08-19T14:07:27.946Z, type=java, title=java记录, content=这里是java记录}
{creator=creator7, createTime=2020-08-19T14:07:28.113Z, type=vue, title=vue记录, content=这里是vue记录}
{creator=creator0, field=nullappend, createTime=2020-08-19T14:32:37.804Z, type=杂文, title=杂文记录, content=修改后的XXXXXXXX}
2. 组合条件以及分页查询、高亮显示
private static void search() throws IOException { String defaultIndex = "news"; // on startup RestHighLevelClient client = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http"), new HttpHost("localhost", 19200, "http"))); // 创建SearchRequest,可以指定Index,也可以不指定。不指定查询所有 SearchRequest searchRequest = new SearchRequest(defaultIndex); // SearchRequest searchRequest = new SearchRequest(defaultIndex); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); // 查询所有 // searchSourceBuilder.query(QueryBuilders.matchAllQuery()); // 查询type是杂文 searchSourceBuilder.query(QueryBuilders.termQuery("content", "后")); // 类似于分页参数 searchSourceBuilder.from(0); searchSourceBuilder.size(2); // 排序 searchSourceBuilder.sort(new ScoreSortBuilder().order(SortOrder.DESC)); // 分数排序 searchSourceBuilder.sort(new FieldSortBuilder("createTime").order(SortOrder.ASC));// 时间升序 // 过滤指定的列。可以指定只搜索的列,也可以指定排除的列,也可以同时指定,同时指定include优先级高 searchSourceBuilder.fetchSource(true); String[] includeFields = new String[] { "createTime", "innerObject.*" }; String[] excludeFields = new String[] { "title" }; searchSourceBuilder.fetchSource(null, excludeFields); // 高亮 HighlightBuilder highlightBuilder = new HighlightBuilder(); HighlightBuilder.Field highlightTitle = new HighlightBuilder.Field("content"); highlightBuilder.field(highlightTitle); searchSourceBuilder.highlighter(highlightBuilder); searchRequest.source(searchSourceBuilder); SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT); SearchHits hits = searchResponse.getHits(); TotalHits totalHits = hits.getTotalHits(); // the total number of hits, must be interpreted in the context of // totalHits.relation long numHits = totalHits.value; System.out.println("numHits " + numHits); // whether the number of hits is accurate (EQUAL_TO) or a lower bound of // the total (GREATER_THAN_OR_EQUAL_TO) TotalHits.Relation relation = totalHits.relation; float maxScore = hits.getMaxScore(); System.out.println("maxScore " + maxScore); SearchHit[] searchHits = hits.getHits(); for (SearchHit hit : searchHits) { // do something with the SearchHit Map<String, HighlightField> highlightFields = hit.getHighlightFields(); System.out.println(highlightFields); Map<String, Object> sourceAsMap = hit.getSourceAsMap(); System.out.println(sourceAsMap); } // on shutdown client.close(); }
结果:
numHits 2
maxScore NaN
{content=[content], fragments[[修改<em>后</em>的XXXXXXXX]]}
{creator=creator0, field=nullappend, createTime=2020-08-19T14:32:37.804Z, type=杂文, content=修改后的XXXXXXXX}
{content=[content], fragments[[修改<em>后</em>的XXXXXXXX]]}
{creator=creator0, createTime=2020-08-19T14:07:21.696Z, type=杂文, content=修改后的XXXXXXXX}
3. 使用QueryBuilder DSL语法构建查询
private static void search() throws IOException { String defaultIndex = "news"; // on startup RestHighLevelClient client = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http"), new HttpHost("localhost", 19200, "http"))); // 创建SearchRequest,可以指定Index,也可以不指定。不指定查询所有 SearchRequest searchRequest = new SearchRequest(defaultIndex); // SearchRequest searchRequest = new SearchRequest(defaultIndex); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); // 可以结合Query DSL BoolQueryBuilder filter = QueryBuilders.boolQuery().must(QueryBuilders.termQuery("content", "后")) .mustNot(QueryBuilders.termQuery("field", "nullappend")); searchSourceBuilder.query(filter); searchRequest.source(searchSourceBuilder); SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT); SearchHits hits = searchResponse.getHits(); TotalHits totalHits = hits.getTotalHits(); // the total number of hits, must be interpreted in the context of // totalHits.relation long numHits = totalHits.value; System.out.println("numHits " + numHits); // whether the number of hits is accurate (EQUAL_TO) or a lower bound of // the total (GREATER_THAN_OR_EQUAL_TO) TotalHits.Relation relation = totalHits.relation; float maxScore = hits.getMaxScore(); System.out.println("maxScore " + maxScore); SearchHit[] searchHits = hits.getHits(); for (SearchHit hit : searchHits) { // do something with the SearchHit Map<String, Object> sourceAsMap = hit.getSourceAsMap(); System.out.println(sourceAsMap); } // on shutdown client.close(); }
结果:
numHits 1
maxScore 0.8898244
{creator=creator0, createTime=2020-08-19T14:07:21.696Z, type=杂文, title=杂文记录, content=修改后的XXXXXXXX}
补充:一些常用的其他DSL查询语法
(1) 查询所有
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery(); boolQueryBuilder.must(QueryBuilders.matchAllQuery()); searchSourceBuilder.query(boolQueryBuilder); searchRequest.source(searchSourceBuilder);
结果:
numHits 9 maxScore 1.0 {creator=creator1, createTime=2020-08-27T02:52:24.491Z, type=java, title=java记录, content=这里是java记录} {creator=creator2, createTime=2020-08-27T02:52:31.677Z, type=vue, title=vue记录, content=这里是vue记录} {creator=creator3, createTime=2020-08-27T02:52:31.915Z, type=js, title=js记录, content=这里是js记录} {creator=creator4, createTime=2020-08-27T02:52:32.067Z, type=es, title=js记录, content=这里是js记录} {creator=creator7, createTime=2020-08-27T02:52:33.733Z, type=vue, title=vue记录, content=这里是vue记录} {creator=creator6, createTime=2020-08-27T02:52:32.395Z, type=java, title=java记录, content=这里是java记录} {creator=creator0, createTime=2020-08-27T02:52:14.353Z, type=杂文, title=杂文记录, content=这里是杂文记录} {creator=creator5, createTime=2020-08-27T02:52:32.202Z, type=杂文, title=杂文记录, content=这里是杂文记录} {creator=creator8, createTime=2020-08-27T02:52:34.030Z, type=js, title=js记录, content=JS是真的强}
(2) 查询类型是java或者vue的-下面用的termQuery,当然可以用termsQuery
1) 不修改权重
private static void search() throws IOException { String defaultIndex = "news"; // on startup RestHighLevelClient client = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http"), new HttpHost("localhost", 19200, "http"))); // 创建SearchRequest,可以指定Index,也可以不指定。不指定查询所有 SearchRequest searchRequest = new SearchRequest(defaultIndex); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery(); boolQueryBuilder.should(QueryBuilders.termQuery("type", "java")); boolQueryBuilder.should(QueryBuilders.termQuery("type", "vue")); searchSourceBuilder.query(boolQueryBuilder); searchRequest.source(searchSourceBuilder); SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT); SearchHits hits = searchResponse.getHits(); TotalHits totalHits = hits.getTotalHits(); // the total number of hits, must be interpreted in the context of // totalHits.relation long numHits = totalHits.value; System.out.println("numHits " + numHits); // whether the number of hits is accurate (EQUAL_TO) or a lower bound of // the total (GREATER_THAN_OR_EQUAL_TO) TotalHits.Relation relation = totalHits.relation; float maxScore = hits.getMaxScore(); System.out.println("maxScore " + maxScore); SearchHit[] searchHits = hits.getHits(); for (SearchHit hit : searchHits) { // do something with the SearchHit Map<String, Object> sourceAsMap = hit.getSourceAsMap(); System.out.println(hit.getScore() + " " + sourceAsMap); } // on shutdown client.close(); }
结果:
numHits 4 maxScore 1.3862942 1.3862942 {creator=creator1, createTime=2020-08-27T02:52:24.491Z, type=java, title=java记录, content=这里是java记录} 0.87546873 {creator=creator2, createTime=2020-08-27T02:52:31.677Z, type=vue, title=vue记录, content=这里是vue记录} 0.87546873 {creator=creator7, createTime=2020-08-27T02:52:33.733Z, type=vue, title=vue记录, content=这里是vue记录} 0.2876821 {creator=creator6, createTime=2020-08-27T02:52:32.395Z, type=java, title=java记录, content=这里是java记录}
2)修改java的权重,优先排列
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery(); boolQueryBuilder.should(QueryBuilders.termQuery("type", "java").boost(20F)); boolQueryBuilder.should(QueryBuilders.termQuery("type", "vue")); searchSourceBuilder.query(boolQueryBuilder); searchRequest.source(searchSourceBuilder);
结果:
numHits 4
maxScore 41.58883
41.58883 {creator=creator1, createTime=2020-08-27T02:52:24.491Z, type=java, title=java记录, content=这里是java记录}
8.630463 {creator=creator6, createTime=2020-08-27T02:52:32.395Z, type=java, title=java记录, content=这里是java记录}
0.87546873 {creator=creator2, createTime=2020-08-27T02:52:31.677Z, type=vue, title=vue记录, content=这里是vue记录}
0.87546873 {creator=creator7, createTime=2020-08-27T02:52:33.733Z, type=vue, title=vue记录, content=这里是vue记录}
4. 聚合查询
首先修改数据都增加一个amount字段:
private static void searchUpdate() throws IOException { String defaultIndex = "news"; // on startup RestHighLevelClient client = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http"), new HttpHost("localhost", 19200, "http"))); // 创建SearchRequest,可以指定Index,也可以不指定。不指定查询所有 SearchRequest searchRequest = new SearchRequest(defaultIndex); // SearchRequest searchRequest = new SearchRequest(defaultIndex); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); searchSourceBuilder.query(QueryBuilders.matchAllQuery()); searchRequest.source(searchSourceBuilder); SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT); SearchHits hits = searchResponse.getHits(); TotalHits totalHits = hits.getTotalHits(); // the total number of hits, must be interpreted in the context of // totalHits.relation long numHits = totalHits.value; System.out.println("numHits " + numHits); // whether the number of hits is accurate (EQUAL_TO) or a lower bound of // the total (GREATER_THAN_OR_EQUAL_TO) TotalHits.Relation relation = totalHits.relation; float maxScore = hits.getMaxScore(); System.out.println("maxScore " + maxScore); // 修改数据 SearchHit[] searchHits = hits.getHits(); int num = 0; for (SearchHit hit : searchHits) { num++; Map<String, Object> sourceAsMap = hit.getSourceAsMap(); sourceAsMap.put("amount", num); String id = hit.getId(); UpdateRequest request = new UpdateRequest(defaultIndex, id).doc(sourceAsMap); client.update(request, RequestOptions.DEFAULT); } // on shutdown client.close(); }
(1) 度量聚合==统计某个数值字段的信息,数值计量聚合操作是能够产生具体的数值的一种计量聚合操作。例如查询总数:其他查询max、min、avg类似
private static void search() throws IOException { String defaultIndex = "news"; // on startup RestHighLevelClient client = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http"), new HttpHost("localhost", 19200, "http"))); // 创建SearchRequest,可以指定Index,也可以不指定。不指定查询所有 SearchRequest searchRequest = new SearchRequest(defaultIndex); // SearchRequest searchRequest = new SearchRequest(defaultIndex); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); searchRequest.source(searchSourceBuilder); // 聚合 ( text类型不能用于索引或排序d) // total 相当于是起的别名 SumAggregationBuilder aggregation = AggregationBuilders.sum("total").field("amount"); searchSourceBuilder.aggregation(aggregation); SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT); Sum agg = searchResponse.getAggregations().get("total"); double value = agg.getValue(); System.out.println(value); // on shutdown client.close(); }
结果:
45.0
也可以用stats直接查询所有
private static void search() throws IOException { String defaultIndex = "news"; // on startup RestHighLevelClient client = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http"), new HttpHost("localhost", 19200, "http"))); // 创建SearchRequest,可以指定Index,也可以不指定。不指定查询所有 SearchRequest searchRequest = new SearchRequest(defaultIndex); // SearchRequest searchRequest = new SearchRequest(defaultIndex); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); searchRequest.source(searchSourceBuilder); // 聚合 ( text类型不能用于索引或排序d) // stats 相当于是起的别名 StatsAggregationBuilder aggregation = AggregationBuilders.stats("stats").field("amount"); searchSourceBuilder.aggregation(aggregation); SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT); Stats agg = searchResponse.getAggregations().get("stats"); double min = agg.getMin(); double max = agg.getMax(); double avg = agg.getAvg(); double sum = agg.getSum(); long count = agg.getCount(); System.out.println(min); System.out.println(max); System.out.println(avg); System.out.println(sum); System.out.println(count); // on shutdown client.close(); }
结果:
1.0
9.0
5.0
45.0
9
(2) 桶分聚合=与度量聚合相比,Bucket聚合可以保存子聚合,这些子聚合将针对由其“父”bucket聚合创建的bucket进行聚合。
1) 词元聚合
private static void search() throws IOException { String defaultIndex = "news"; // on startup RestHighLevelClient client = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http"), new HttpHost("localhost", 19200, "http"))); // 创建SearchRequest,可以指定Index,也可以不指定。不指定查询所有 SearchRequest searchRequest = new SearchRequest(defaultIndex); // SearchRequest searchRequest = new SearchRequest(defaultIndex); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); searchRequest.source(searchSourceBuilder); // 聚合 ( text类型不能用于索引或排序,如果是text可以用 filed.keyword转换)。按统计的数量升序排序 TermsAggregationBuilder field = AggregationBuilders.terms("types").field("type").order(BucketOrder.count(true)); searchSourceBuilder.aggregation(field); SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT); Terms genders = searchResponse.getAggregations().get("types"); // For each entry for (Terms.Bucket entry : genders.getBuckets()) { Object key = entry.getKey(); // Term long docCount = entry.getDocCount(); // Doc count System.out.println(key); System.out.println(docCount); } // on shutdown client.close(); }
结果:
es
1
vue
1
java
2
js
2
杂文
3
2) 词元聚合+子聚合实现求总数、均值
private static void search() throws IOException { String defaultIndex = "news"; // on startup RestHighLevelClient client = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http"), new HttpHost("localhost", 19200, "http"))); // 创建SearchRequest,可以指定Index,也可以不指定。不指定查询所有 SearchRequest searchRequest = new SearchRequest(defaultIndex); // SearchRequest searchRequest = new SearchRequest(defaultIndex); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); searchRequest.source(searchSourceBuilder); // 聚合 ( text类型不能用于索引或排序,如果是text可以用 filed.keyword转换)。按统计的数量升序排序 TermsAggregationBuilder field = AggregationBuilders.terms("types").field("type").order(BucketOrder.count(true)); field.subAggregation(AggregationBuilders.avg("avg_amount").field("amount")); searchSourceBuilder.aggregation(field); SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT); Terms types_agg = searchResponse.getAggregations().get("types"); // For each entry List<? extends Bucket> buckets = types_agg.getBuckets(); for (Terms.Bucket entry : buckets) { Object key = entry.getKey(); // Term long docCount = entry.getDocCount(); // Doc count System.out.println(key + " " + docCount); Avg average = entry.getAggregations().get("avg_amount"); System.out.println("均值: " + average.getValue()); } // on shutdown client.close(); }
结果:
es 1
均值: 3.0
vue 1
均值: 8.0
java 2
均值: 6.0
js 2
均值: 4.0
杂文 3
均值: 4.666666666666667
2. MultiSearch
private static void search() throws IOException { String defaultIndex = "news"; // on startup RestHighLevelClient client = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http"), new HttpHost("localhost", 19200, "http"))); // 创建SearchRequest,可以指定Index,也可以不指定。不指定查询所有 MultiSearchRequest request = new MultiSearchRequest(); SearchRequest firstSearchRequest = new SearchRequest(defaultIndex); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); searchSourceBuilder.query(QueryBuilders.matchQuery("type", "java")); firstSearchRequest.source(searchSourceBuilder); request.add(firstSearchRequest); SearchRequest secondSearchRequest = new SearchRequest(defaultIndex); searchSourceBuilder = new SearchSourceBuilder(); searchSourceBuilder.query(QueryBuilders.matchQuery("type", "vue")); secondSearchRequest.source(searchSourceBuilder); request.add(secondSearchRequest); MultiSearchResponse response = client.msearch(request, RequestOptions.DEFAULT); Item[] responses = response.getResponses(); for (Item responseTmp : responses) { System.out.println("==============="); SearchResponse searchResponse = responseTmp.getResponse(); doPrint(searchResponse); } // on shutdown client.close(); } private static void doPrint(SearchResponse searchResponse) { SearchHits hits = searchResponse.getHits(); TotalHits totalHits = hits.getTotalHits(); // the total number of hits, must be interpreted in the context of // totalHits.relation long numHits = totalHits.value; System.out.println("numHits " + numHits); // whether the number of hits is accurate (EQUAL_TO) or a lower bound of // the total (GREATER_THAN_OR_EQUAL_TO) TotalHits.Relation relation = totalHits.relation; float maxScore = hits.getMaxScore(); System.out.println("maxScore " + maxScore); SearchHit[] searchHits = hits.getHits(); for (SearchHit hit : searchHits) { // do something with the SearchHit Map<String, Object> sourceAsMap = hit.getSourceAsMap(); System.out.println(sourceAsMap); } }
结果:
===============
numHits 2
maxScore 0.87546873
{creator=creator6, amount=7, createTime=2020-08-19T14:07:27.946Z, type=java, title=java记录, content=这里是java记录}
{creator=creator1, amount=5, createTime=2020-08-19T14:07:25.469Z, type=java, title=java记录, content=这里是java记录}
===============
numHits 1
maxScore 1.3862942
{creator=creator7, amount=8, createTime=2020-08-19T14:07:28.113Z, type=vue, title=vue记录, content=这里是vue记录}
3.Count 查询数量
private static void search() throws IOException { String defaultIndex = "news"; // on startup RestHighLevelClient client = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http"), new HttpHost("localhost", 19200, "http"))); CountRequest countRequest = new CountRequest(); countRequest.indices(defaultIndex); // 创建查询条件 SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); sourceBuilder.query(QueryBuilders.termQuery("type", "java")); countRequest.source(sourceBuilder); CountResponse countResponse = client.count(countRequest, RequestOptions.DEFAULT); long count = countResponse.getCount(); System.out.println("count " + count); RestStatus status = countResponse.status(); System.out.println("status " + status); Boolean terminatedEarly = countResponse.isTerminatedEarly(); System.out.println("terminatedEarly " + terminatedEarly); int totalShards = countResponse.getTotalShards(); System.out.println("totalShards " + totalShards); int skippedShards = countResponse.getSkippedShards(); System.out.println("skippedShards " + skippedShards); int successfulShards = countResponse.getSuccessfulShards(); System.out.println("successfulShards " + successfulShards); int failedShards = countResponse.getFailedShards(); System.out.println("failedShards " + failedShards); if (countResponse.getShardFailures() != null) { for (ShardSearchFailure failure : countResponse.getShardFailures()) { // failures should be handled here } } // on shutdown client.close(); }
结果:
count 2
status OK
terminatedEarly null
totalShards 3
skippedShards 0
successfulShards 3
failedShards 0
补充:AnalyzerAPI可以用于分析分词效果,用不同的分词器进行分词,例如:
private static void anylyze() throws IOException { // on startup RestHighLevelClient client = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http"))); AnalyzeRequest request = AnalyzeRequest.withGlobalAnalyzer("standard", "我是一个程序员", "I am cxy!"); request.explain(true); AnalyzeResponse response = client.indices().analyze(request, RequestOptions.DEFAULT); DetailAnalyzeResponse detail = response.detail(); AnalyzeTokenList analyzer = detail.analyzer(); String name = analyzer.getName(); System.out.println(name); System.out.println("=============="); AnalyzeToken[] tokens1 = analyzer.getTokens(); for (AnalyzeToken t : tokens1) { System.out.println(t.getTerm() + " " + t.getStartOffset() + " " + t.getEndOffset() + " " + t.getType()); } // on shutdown client.close(); }
结果:
standard
==============
我 0 1 <IDEOGRAPHIC>
是 1 2 <IDEOGRAPHIC>
一 2 3 <IDEOGRAPHIC>
个 3 4 <IDEOGRAPHIC>
程 4 5 <IDEOGRAPHIC>
序 5 6 <IDEOGRAPHIC>
员 6 7 <IDEOGRAPHIC>
i 8 9 <ALPHANUM>
am 10 12 <ALPHANUM>
cxy 13 16 <ALPHANUM>
用ik_smart分词分析效果如下:
org.wltea.analyzer.lucene.IKAnalyzer
==============
我 0 1 CN_CHAR
是 1 2 CN_CHAR
一个 2 4 CN_WORD
程序员 4 7 CN_WORD
i 8 9 ENGLISH
am 10 12 ENGLISH
cxy 13 16 ENGLISH
补充:ES的text字段不能聚合,需要用keyword字段进行聚合