簡單研究下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 + "\t" + 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() + "\t" + 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 + "\t" + docCount); Avg average = entry.getAggregations().get("avg_amount"); System.out.println("均值: \t" + 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" + t.getStartOffset() + "\t" + t.getEndOffset() + "\t" + 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字段進行聚合