在上一篇中,我們介紹瞭如何使用Java客戶端對elasticsearch進行索引的創建、mapping信息的設置和文檔的添加,在本篇中我們將主要介紹通過Java客戶端查詢文檔的操作。
使用Java客戶端查詢操作步驟
- 創建一個client對象
- 創建一個查詢對象,通過QueryBuilders進行創建,其由很多實現的子類。
- 使用client執行查詢操作,需提前設置查詢參數
- 得到查詢返回的結果,默認返回十條數據(如果返回條數過多,可能會導致內存溢出)。通過返回接口可以取查詢結果的記錄數,去查詢結果列表等信息。
- 關閉client對象。
根據ID查詢文檔
通過前面的學習,我們知道在添加文檔時,elasticsearch會持有一個主鍵即"_id"。在查詢時可以通過這個主鍵進行查詢,示例demo如下所示。
@Test
public void queryById() throws UnknownHostException {
ElasticSearchParams elasticSearchParams = new ElasticSearchParams();
elasticSearchParams.setIndexName("20200128-xinghaol")
.setIp("47.107.90.36")
.setClusterName("my-elasticsearch")
.setPort(9300);
SearchResponse searchResponse = ElasticSearchUtil.queryById(elasticSearchParams);
SearchHits searchHits = searchResponse.getHits();
System.out.println("總數:" + searchHits.getTotalHits());
SearchHit[] hits = searchHits.getHits();
for (int i = 0; i < hits.length; i++) {
SearchHit searchHit = hits[i];
System.out.println("查詢結果爲:" + (i + 1) + " " + searchHit.getSourceAsString());
}
}
public static SearchResponse queryById(ElasticSearchParams elasticSearchParams) throws UnknownHostException {
TransportClient transportClient = buildTransportClient(elasticSearchParams);
// 需要加判空
// 查詢id爲1的記錄
QueryBuilder queryBuilder = QueryBuilders.idsQuery().addIds("1");
SearchResponse searchResponse = transportClient.prepareSearch(elasticSearchParams.getIndexName())
.setTypes(elasticSearchParams.getDocumentTypes())
.setQuery(queryBuilder)
.get();
return searchResponse;
}
private static TransportClient buildTransportClient(ElasticSearchParams elasticSearchParams) throws UnknownHostException {
if (Objects.isNull(elasticSearchParams) || Strings.isNullOrEmpty(elasticSearchParams.getIndexName())
|| Strings.isNullOrEmpty(elasticSearchParams.getIp())
|| Objects.isNull(elasticSearchParams.getPort())
|| Strings.isNullOrEmpty(elasticSearchParams.getClusterName())
|| elasticSearchParams.getPort() <= 0) {
log.error("參數不合法");
return null;
}
// 創建Settings
Settings settings = Settings.builder()
.put("cluster.name", elasticSearchParams.getClusterName())
.put("client.transport.ignore_cluster_name", true)
.build();
// 創建transportclient對象
TransportClient transportClient = new PreBuiltTransportClient(settings);
transportClient.addTransportAddress(new TransportAddress(InetAddress.getByName(elasticSearchParams.getIp()), elasticSearchParams.getPort()));
return transportClient;
}
在SearchResponse對象中可以得到查詢結果的各種信息,比如文檔總條數、文檔內容等。
根據Term方式查詢
根據Trem方式查詢與根據ID查詢唯一的區別點在於在創建QueryBuilder時爲termQuery(name,value)形式的實現方式,如下所示。
QueryBuilder queryBuilder = QueryBuilders.termQuery(elasticSearchParams.getTermQueryName(), elasticSearchParams.getTermQueryValue());
在得到SearchResponse後,與根據ID查詢的後續操作相同,這裏不再贅述。
根據QueryString查詢
在前面介紹elasticsearch查詢方式時,elasticsearch支持根據字符串的查詢,Java客戶端同樣支持根據字符串的查詢。在創建QueryBuilder時選擇queryStringQuery()的實現方式,可以指定默認的搜索域,若不指定搜索域則在所有的與進行查詢操作,其他操作不在贅述。
查詢elasticsearch分頁設置
在上面的查詢操作中,我們介紹了elasticsearch默認是返回10條查詢數據,但是如果我們想要查詢更多或者分頁查詢操作該怎麼辦?在Java客戶端中transprotClient查詢之前設置起始行號和每頁顯示的條數,示例如下。
transportClient.prepareSearch(elasticSearchParams.getIndexName())
.setTypes(elasticSearchParams.getDocumentTypes())
.setFrom(elasticSearchParams.getFrom())
.setSize(elasticSearchParams.getSize())
.setQuery(queryBuilder);
在查詢結果中高亮顯示
在使用百度、Google等搜索引擎時,查詢出的結果都高亮顯示了我們搜索的關鍵字,在elasticsearch中同樣支持高亮的設置。在查詢時需要指定一個高亮顯示的字段,並且需要指定高亮顯示的前綴和後綴,並將這些設置到client中,查詢得到結果後可以查看高亮顯示的結果。
使用HighlightBuilder設置要高亮的字段名稱,以及要添加的前綴、後綴名稱。在查詢之前設置HighlightBuilder到transportClient中,實例代碼如下所示。
@Test
public void queryHighLighter() throws UnknownHostException {
ElasticSearchParams elasticSearchParams = new ElasticSearchParams();
elasticSearchParams.setIndexName("20200126-xinghaol")
.setIp("47.107.90.36")
.setClusterName("my-elasticsearch")
.setPort(9300);
TransportClient transportClient = ElasticSearchUtil.obtainTransport(elasticSearchParams);
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.field("house_name");
highlightBuilder.preTags("<em>");
highlightBuilder.postTags("</em>");
QueryBuilder queryBuilder = QueryBuilders.queryStringQuery("小屋").defaultField("house_name");
SearchResponse searchResponse = transportClient.prepareSearch().
setQuery(queryBuilder).
highlighter(highlightBuilder).get();
SearchHits searchHits = searchResponse.getHits();
SearchHit[] hits = searchHits.getHits();
for (int i = 0; i < hits.length; i++) {
SearchHit searchHit = hits[i];
Map<String, HighlightField> highlightFields = searchHit.getHighlightFields();
HighlightField highlightField = highlightFields.get("house_name");
Text[] fragments = highlightField.getFragments();
if (fragments != null) {
System.out.println("當前是第" + i + "個文檔,文檔內容:" + fragments[0].toString());
}
}
}
運行上面demo示例得到如下結果,可以看到分詞後的都已經加上了<em>標籤,即完成了高亮顯示的要求。
當前是第0個文檔,文檔內容:<em>小</em>數點價格房<em>屋</em>01
當前是第1個文檔,文檔內容:龍捲風<em>小屋</em>
當前是第2個文檔,文檔內容:愛的<em>小屋</em>
當前是第3個文檔,文檔內容:這是我修改的房<em>屋</em>名稱
當前是第4個文檔,文檔內容:閃訂房<em>屋</em>20200119
小節
在本篇中我們通過Java客戶端完成了根據ID、關鍵詞、字符串的查詢方式,還介紹了elasticsearch中的分頁設置及高亮顯示的查詢。希望對初學者有所幫助。