国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

SpringBoot操作ES進(jìn)行各種高級(jí)查詢(值得收藏)

這篇具有很好參考價(jià)值的文章主要介紹了SpringBoot操作ES進(jìn)行各種高級(jí)查詢(值得收藏)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

SpringBoot整合ES

創(chuàng)建SpringBoot項(xiàng)目,導(dǎo)入 ES 6.2.1 的 RestClient 依賴和 ES 依賴。在項(xiàng)目中直接引用 es-starter 的話會(huì)報(bào)容器初始化異常錯(cuò)誤,導(dǎo)致項(xiàng)目無(wú)法啟動(dòng)。如果有讀者解決了這個(gè)問(wèn)題,歡迎留言交流

<!--?ES?客戶端?-->
<dependency>
????<groupId>org.elasticsearch.client</groupId>
????<artifactId>elasticsearch-rest-high-level-client</artifactId>
????<version>${elasticsearch.version}</version>
</dependency>
<!--?ES?版本?-->
<dependency>
????<groupId>org.elasticsearch</groupId>
????<artifactId>elasticsearch</artifactId>
????<version>${elasticsearch.version}</version>
</dependency>

為容器定義 RestClient 對(duì)象

/**
?*?在Spring容器中定義?RestClient?對(duì)象
?*?@Author:?keats_coder
?*?@Version?1.0
?*?*/
@Configuration
public?class?ESConfig?{
????@Value("${yunshangxue.elasticsearch.hostlist}")
????private?String?hostlist;?//?127.0.0.1:9200

????@Bean?//?高版本客戶端
????public?RestHighLevelClient?restHighLevelClient()?{
????????//?解析 hostlist 配置信息。假如以后有多個(gè),則需要用?,?分開(kāi)
????????String[]?split?=?hostlist.split(",");
????????//?創(chuàng)建?HttpHost?數(shù)組,其中存放es主機(jī)和端口的配置信息
????????HttpHost[]?httpHostArray?=?new?HttpHost[split.length];
????????for?(int?i?=?0;?i?<?split.length;?i++)?{
????????????String?item?=?split[i];
????????????httpHostArray[i]?=?new?HttpHost(item.split(":")[0],?Integer.parseInt(item.split(":")[1]),?"http");
????????}
????????//?創(chuàng)建RestHighLevelClient客戶端
????????return?new?RestHighLevelClient(RestClient.builder(httpHostArray));
????}

????//?項(xiàng)目主要使用?RestHighLevelClient,對(duì)于低級(jí)的客戶端暫時(shí)不用
????@Bean
????public?RestClient?restClient()?{
????????//?解析hostlist配置信息
????????String[]?split?=?hostlist.split(",");
????????//?創(chuàng)建HttpHost數(shù)組,其中存放es主機(jī)和端口的配置信息
????????HttpHost[]?httpHostArray?=?new?HttpHost[split.length];
????????for?(int?i?=?0;?i?<?split.length;?i++)?{
????????????String?item?=?split[i];
????????????httpHostArray[i]?=?new?HttpHost(item.split(":")[0],?Integer.parseInt(item.split(":")[1]),?"http");
????????}
????????return?RestClient.builder(httpHostArray).build();
????}
}

在 yml 文件中配置 eshost

yunshangxue:
??elasticsearch:
????hostlist:?${eshostlist:127.0.0.1:9200}

調(diào)用相關(guān) API 執(zhí)行操作

  • 創(chuàng)建操作索引的對(duì)象

  • 構(gòu)建操作索引的請(qǐng)求

  • 調(diào)用對(duì)象的相關(guān)API發(fā)送請(qǐng)求

  • 獲取響應(yīng)消息

/**
?*?刪除索引庫(kù)
?*/
@Test
public?void?testDelIndex()?throws?IOException?{
????//?操作索引的對(duì)象
????IndicesClient?indices?=?client.indices();
????//?刪除索引的請(qǐng)求
????DeleteIndexRequest?deleteIndexRequest?=?new?DeleteIndexRequest("ysx_course");
????//?刪除索引
????DeleteIndexResponse?response?=?indices.delete(deleteIndexRequest);
????//?得到響應(yīng)
????boolean?b?=?response.isAcknowledged();
????System.out.println(b);
}

創(chuàng)建索引, 步驟和刪除類似,需要注意的是刪除的時(shí)候需要指定 ES 庫(kù)分片的數(shù)量和副本的數(shù)量,并且在創(chuàng)建索引的時(shí)候可以將映射一起指定了。代碼如下

public?void?testAddIndex()?throws?IOException?{
????//?操作索引的對(duì)象
????IndicesClient?indices?=?client.indices();
????//?創(chuàng)建索引的請(qǐng)求
????CreateIndexRequest?request?=?new?CreateIndexRequest("ysx_course");
????request.settings(Settings.builder().put("number_of_shards",?"1").put("number_of_replicas",?"0"));
????//?創(chuàng)建映射
????request.mapping("doc",?"{\n"?+
????????????"????????????????\"properties\":?{\n"?+
????????????"????????????????????\"description\":?{\n"?+
????????????"????????????????????????\"type\":?\"text\",\n"?+
????????????"????????????????????????\"analyzer\":?\"ik_max_word\",\n"?+
????????????"????????????????????????\"search_analyzer\":?\"ik_smart\"\n"?+
????????????"????????????????????},\n"?+
????????????"????????????????????\"name\":?{\n"?+
????????????"????????????????????????\"type\":?\"text\",\n"?+
????????????"????????????????????????\"analyzer\":?\"ik_max_word\",\n"?+
????????????"????????????????????????\"search_analyzer\":?\"ik_smart\"\n"?+
????????????"????????????????????},\n"?+
????????????"\"pic\":{????????????????????\n"?+
????????????"\"type\":\"text\",????????????????????????\n"?+
????????????"\"index\":false????????????????????????\n"?+
????????????"},????????????????????\n"?+
????????????"????????????????????\"price\":?{\n"?+
????????????"????????????????????????\"type\":?\"float\"\n"?+
????????????"????????????????????},\n"?+
????????????"????????????????????\"studymodel\":?{\n"?+
????????????"????????????????????????\"type\":?\"keyword\"\n"?+
????????????"????????????????????},\n"?+
????????????"????????????????????\"timestamp\":?{\n"?+
????????????"????????????????????????\"type\":?\"date\",\n"?+
????????????"????????????????????????\"format\":?\"yyyy-MM‐dd?HH:mm:ss||yyyy‐MM‐dd||epoch_millis\"\n"?+
????????????"????????????????????}\n"?+
????????????"????????????????}\n"?+
????????????"????????????}",?XContentType.JSON);


????//?執(zhí)行創(chuàng)建操作
????CreateIndexResponse?response?=?indices.create(request);
????//?得到響應(yīng)
????boolean?b?=?response.isAcknowledged();
????System.out.println(b);
}

Java API操作ES

準(zhǔn)備數(shù)據(jù)環(huán)境

創(chuàng)建索引:ysx_course

創(chuàng)建映射:

PUT http://localhost:9200/ysx_course/doc/_mapping

{
????"properties":?{
????????"description":?{?//?課程描述
????????????"type":?"text",?//?String?text?類型
????????????"analyzer":?"ik_max_word", //?存入的分詞模式:細(xì)粒度
????????????"search_analyzer":?"ik_smart"?//?查詢的分詞模式:粗粒度
????????},
????????"name":?{?//?課程名稱
????????????"type":?"text",
????????????"analyzer":?"ik_max_word",
????????????"search_analyzer":?"ik_smart"
????????},
????????"pic":{?//?圖片地址
????????????"type":"text",?
????????????"index":false?//?地址不用來(lái)搜索,因此不為它構(gòu)建索引
????????},
????????"price":?{?//?價(jià)格
?????????"type":?"scaled_float",?//?有比例浮點(diǎn)
?????????"scaling_factor":?100?//?比例因子?100
????????},
????????"studymodel":?{
????????????"type":?"keyword"?//?不分詞,全關(guān)鍵字匹配
????????},
????????"timestamp":?{
????????????"type":?"date",
????????????"format":?"yyyy-MM-dd?HH:mm:ss||yyyy-MM-dd||epoch_millis"
????????}
????}
}

加入原始數(shù)據(jù):

POST http://localhost:9200/ysx_course/doc/1

{
?"name":?"Bootstrap開(kāi)發(fā)",
?"description":?"Bootstrap是由Twitter推出的一個(gè)前臺(tái)頁(yè)面開(kāi)發(fā)框架,是一個(gè)非常流行的開(kāi)發(fā)框架,此框架集成了多種頁(yè)面效果。此開(kāi)發(fā)框架包含了大量的CSS、JS程序代碼,可以幫助開(kāi)發(fā)者(尤其是不擅長(zhǎng)頁(yè)面開(kāi)發(fā)的程序人員)輕松的實(shí)現(xiàn)一個(gè)不受瀏覽器限制的精美界面效果。",
?"studymodel":?"201002",
?"price":38.6,
?"timestamp":"2018-04-25?19:11:35",
?"pic":"group1/M00/00/00/wKhlQFs6RCeAY0pHAAJx5ZjNDEM428.jpg"
}

DSL搜索

DSL(Domain Specific Language)是ES提出的基于json的搜索方式,在搜索時(shí)傳入特定的json格式的數(shù)據(jù)來(lái)完成不同的搜索需求。DSL比URI搜索方式功能強(qiáng)大,在項(xiàng)目中建議使用DSL方式來(lái)完成搜索。

查詢?nèi)?/p>

原本我們想要查詢?nèi)康脑?,需要使?GET 請(qǐng)求發(fā)送?_search?命令,如今使用 DSL 方式搜索,可以使用 POST 請(qǐng)求,并在請(qǐng)求體中設(shè)置 JSON 字符串來(lái)構(gòu)建查詢條件

POST http://localhost:9200/ysx_course/doc/_search

請(qǐng)求體 JSON

{?
????"query":?{
????????"match_all":?{}?//?查詢?nèi)?????},
????"_source"?:?["name","studymodel"]?//?查詢結(jié)果包括?課程名?+?學(xué)習(xí)模式兩個(gè)映射
}

具體的測(cè)試方法如下:過(guò)程比較繁瑣,好在條理還比較清晰

//?搜索全部記錄
@Test
public?void?testSearchAll()?throws?IOException,?ParseException?{
????//?搜索請(qǐng)求對(duì)象
????SearchRequest?searchRequest?=?new?SearchRequest("ysx_course");
????//?指定類型
????searchRequest.types("doc");
????//?搜索源構(gòu)建對(duì)象
????SearchSourceBuilder?searchSourceBuilder?=?new?SearchSourceBuilder();
????//?搜索方式
????//?matchAllQuery搜索全部
????searchSourceBuilder.query(QueryBuilders.matchAllQuery());
????//?設(shè)置源字段過(guò)慮,第一個(gè)參數(shù)結(jié)果集包括哪些字段,第二個(gè)參數(shù)表示結(jié)果集不包括哪些字段
????searchSourceBuilder.fetchSource(new?String[]{"name","studymodel","price","timestamp"},new?String[]{});
????//?向搜索請(qǐng)求對(duì)象中設(shè)置搜索源
????searchRequest.source(searchSourceBuilder);
????//?執(zhí)行搜索,向ES發(fā)起http請(qǐng)求
????SearchResponse?searchResponse?=?client.search(searchRequest);
????//?搜索結(jié)果
????SearchHits?hits?=?searchResponse.getHits();
????//?匹配到的總記錄數(shù)
????long?totalHits?=?hits.getTotalHits();
????//?得到匹配度高的文檔
????SearchHit[]?searchHits?=?hits.getHits();
????//?日期格式化對(duì)象
????SimpleDateFormat?dateFormat?=?new?SimpleDateFormat("yyyy-MM-dd?HH:mm:ss");
????for(SearchHit?hit:searchHits){
????????//?文檔的主鍵
????????String?id?=?hit.getId();
????????//?源文檔內(nèi)容
????????Map<String,?Object>?sourceAsMap?=?hit.getSourceAsMap();
????????String?name?=?(String)?sourceAsMap.get("name");
????????//?由于前邊設(shè)置了源文檔字段過(guò)慮,這時(shí)description是取不到的
????????String?description?=?(String)?sourceAsMap.get("description");
????????//?學(xué)習(xí)模式
????????String?studymodel?=?(String)?sourceAsMap.get("studymodel");
????????//?價(jià)格
????????Double?price?=?(Double)?sourceAsMap.get("price");
????????//?日期
????????Date?timestamp?=?dateFormat.parse((String)?sourceAsMap.get("timestamp"));
????????System.out.println(name);
????????System.out.println(studymodel);
????????System.out.println("你看不見(jiàn)我,看不見(jiàn)我~"?+?description);
????????System.out.println(price);
????}

}

坑:

執(zhí)行過(guò)程中遇到的問(wèn)題:不能對(duì)這個(gè)值進(jìn)行初始化,導(dǎo)致 Spring 容器無(wú)法初始化

Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'yunshangxue.elasticsearch.hostlist' in value "${yunshangxue.elasticsearch.hostlist}"

通過(guò)檢查 target 目錄發(fā)現(xiàn),生成的 target 文件包中沒(méi)有將 yml 配置文件帶過(guò)來(lái)... 仔細(xì)對(duì)比發(fā)現(xiàn),我的項(xiàng)目竟然變成了一個(gè)不是 Maven 的項(xiàng)目。重新使用 IDEA 導(dǎo)入 Mavaen 工程之后便能正常運(yùn)行了。

推薦:Java面試練題寶典

分頁(yè)查詢

我們來(lái) look 一下 ES 的分頁(yè)查詢參數(shù):

{?
????//?from?起始索引
????//?size?每頁(yè)顯示的條數(shù)
????"from"?:?0,?"size"?:?1,
????"query":?{
???????"match_all":?{}
?????},
????"_source"?:?["name","studymodel"]
}

SpringBoot操作ES進(jìn)行各種高級(jí)查詢(值得收藏)

通過(guò)查詢結(jié)果可以發(fā)現(xiàn),我們?cè)O(shè)置了分頁(yè)參數(shù)之后, hits.total 仍然是 3,表示它找到了 3 條數(shù)據(jù),而按照分頁(yè)規(guī)則,它只會(huì)返回一條數(shù)據(jù),因此 hits.hits 里面只有一條數(shù)據(jù)。這也符合我們的業(yè)務(wù)規(guī)則,在查詢前端頁(yè)面顯示總共的條數(shù)和當(dāng)前的數(shù)據(jù)。

由此,我們就可以通過(guò) Java API 來(lái)構(gòu)建查詢條件了:對(duì)上面查詢?nèi)康拇a進(jìn)行如下改造:

//?搜索源構(gòu)建對(duì)象
SearchSourceBuilder?searchSourceBuilder?=?new?SearchSourceBuilder();
int?page?=?2;?//?頁(yè)碼
int?size?=?1;?//?每頁(yè)顯示的條數(shù)
int?index?=?(page?-?1)?*?size;
searchSourceBuilder.from(index);
searchSourceBuilder.size(1);
//?搜索方式
//?matchAllQuery搜索全部
searchSourceBuilder.query(QueryBuilders.matchAllQuery());

精確查詢 TermQuery

Term Query為精確查詢,在搜索時(shí)會(huì)整體匹配關(guān)鍵字,不再將關(guān)鍵字分詞

例如:

{
????"query":?{
?????"term":?{?//?查詢的方式為?term?精確查詢
??????"name":?"spring"?//?查詢的字段為?name?關(guān)鍵字是?spring
?????}
????},
????"_source":?[
????????"name",
????????"studymodel"
????]
}

此時(shí)查詢的結(jié)果是:

?"hits":?[
?????{
?????????"_index":?"ysx_course",
?????????"_type":?"doc",
?????????"_id":?"3",
?????????"_score":?0.9331132,
?????????"_source":?{
?????????????"studymodel":?"201001",
?????????????"name":?"spring開(kāi)發(fā)基礎(chǔ)"
?????????}
?????}
?]

查詢到了上面這條數(shù)據(jù),因?yàn)?spring開(kāi)發(fā)基礎(chǔ) 分完詞后是 spring 開(kāi)發(fā) 基礎(chǔ) ,而查詢關(guān)鍵字是 spring 不分詞,這樣當(dāng)然可以匹配到這條記錄,但是當(dāng)我們修改關(guān)鍵字為 spring開(kāi)發(fā),按照往常的查詢方法,也是可以查詢到的。但是 term 不一樣,它不會(huì)對(duì)關(guān)鍵字分詞。結(jié)果可想而知是查詢不到的

JavaAPI如下:

//?搜索方式
//?termQuery?精確查詢
searchSourceBuilder.query(QueryBuilders.termQuery("studymodel",?"201002"));

根據(jù) ID 查詢:

根據(jù) ID 精確查詢和根據(jù)其他條件精確查詢是一樣的,不同的是 id 字段前面有一個(gè)下劃線注意寫(xiě)上

searchSourceBuilder.query(QueryBuilders.termQuery("_id",?"1"));

但是,當(dāng)一次查詢多個(gè) ID 時(shí),相應(yīng)的 API 也應(yīng)該改變,使用 termsQuery 而不是 termQuery。多了一個(gè) s

全文檢索 MatchQuery

MatchQuery 即全文檢索,會(huì)對(duì)關(guān)鍵字進(jìn)行分詞后匹配詞條。

query:搜索的關(guān)鍵字,對(duì)于英文關(guān)鍵字如果有多個(gè)單詞則中間要用半角逗號(hào)分隔,而對(duì)于中文關(guān)鍵字中間可以用逗號(hào)分隔也可以不用

operator:設(shè)置查詢的結(jié)果取交集還是并集,并集用 or, 交集用 and

{
????"query":?{
????????"match":?{
????????????"description":?{
????????????????"query":?"spring開(kāi)發(fā)",
????????????????"operator":?"or"
????????????}
????????}
????}
}

有時(shí),我們需要設(shè)定一個(gè)量化的表達(dá)方式,例如查詢 spring開(kāi)發(fā)基礎(chǔ),這三個(gè)詞條。我們需求是至少匹配兩個(gè)詞條,這時(shí) operator 屬性就不能滿足要求了,ES 還提供了另外一個(gè)屬性:minimum_should_match?用一個(gè)百分?jǐn)?shù)來(lái)設(shè)定應(yīng)該有多少個(gè)詞條滿足要求。例如查詢:

“spring開(kāi)發(fā)框架”會(huì)被分為三個(gè)詞:spring、開(kāi)發(fā)、框架

設(shè)置"minimum_should_match": "80%"表示,三個(gè)詞在文檔的匹配占比為80%,即3*0.8=2.4,向下取整得2,表示至少有兩個(gè)詞在文檔中要匹配成功。

推薦:Java面試練題寶典

JavaAPI

通過(guò) matchQuery.minimumShouldMatch 的方式來(lái)設(shè)置條件

//?matchQuery全文檢索
searchSourceBuilder.query(QueryBuilders.matchQuery("description",?"Spring開(kāi)發(fā)框架").minimumShouldMatch("70%"));

多字段聯(lián)合搜索 MultiQuery

上面的 MatchQuery 有一個(gè)短板,假如用戶輸入了某關(guān)鍵字,我們?cè)诓檎业臅r(shí)候并不知道他輸入的是 name 還是 description,這時(shí)我們用什么都不合適,而 MultiQuery 的出現(xiàn)解決了這個(gè)問(wèn)題,他可以通過(guò) fields 屬性來(lái)設(shè)置多個(gè)域聯(lián)合查找:具體用法如下

{
????"query":?{
????????"multi_match":?{
????????????"query":?"Spring開(kāi)發(fā)",
????????????"minimum_should_match":?"70%",
????????????"fields":?["name",?"description"]
????????}
????}
}

JavaAPI

searchSourceBuilder.query(QueryBuilders.multiMatchQuery("Spring開(kāi)發(fā)框架",?"name",?"description").minimumShouldMatch("70%"));

提升 boost

在多域聯(lián)合查詢的時(shí)候,可以通過(guò) boost 來(lái)設(shè)置某個(gè)域在計(jì)算得分時(shí)候的比重,比重越高的域當(dāng)他符合條件時(shí)計(jì)算的得分越高,相應(yīng)的該記錄也更靠前。通過(guò)在 fields 中給相應(yīng)的字段用 ^權(quán)重倍數(shù)來(lái)實(shí)現(xiàn)

"fields":?["name^10",?"description"]

上面的代碼表示給 name 字段提升十倍權(quán)重,查詢到的結(jié)果:

{
????"_index":?"ysx_course",
????"_type":?"doc",
????"_id":?"3",
????"_score":?13.802518,?//?可以清楚的發(fā)現(xiàn),得分竟然是?13?了
????"_source":?{
????????"name":?"spring開(kāi)發(fā)基礎(chǔ)",
????????"description":?"spring 在java領(lǐng)域非常流行,java程序員都在用。",
????????"studymodel":?"201001",
????????"price":?88.6,
????????"timestamp":?"2018-02-24?19:11:35",
????????"pic":?"group1/M00/00/00/wKhlQFs6RCeAY0pHAAJx5ZjNDEM428.jpg"
????}
},

而在 Java 中,仍然可以通過(guò)鏈?zhǔn)骄幊虂?lái)實(shí)現(xiàn)

searchSourceBuilder.query(QueryBuilders.multiMatchQuery("Spring開(kāi)發(fā)框架",?"name",?"description").field("name",?10));?//?設(shè)置?name?10倍權(quán)重

布爾查詢 BoolQuery

如果我們既要對(duì)一些字段進(jìn)行分詞查詢,同時(shí)要對(duì)另一些字段進(jìn)行精確查詢,就需要使用布爾查詢來(lái)實(shí)現(xiàn)了。布爾查詢對(duì)應(yīng)于Lucene的BooleanQuery查詢,實(shí)現(xiàn)將多個(gè)查詢組合起來(lái),有三個(gè)可選的參數(shù):

must:文檔必須匹配must所包括的查詢條件,相當(dāng)于 “AND”

should:文檔應(yīng)該匹配should所包括的查詢條件其中的一個(gè)或多個(gè),相當(dāng)于 "OR"

must_not:文檔不能匹配must_not所包括的該查詢條件,相當(dāng)于“NOT”

{
????"query":?{
????????"bool":?{?//?布爾查詢
????????????"must":?[?//?查詢條件?must?表示數(shù)組中的查詢方式所規(guī)定的條件都必須滿足
????????????????{
????????????????????"multi_match":?{
????????????????????????"query":?"spring框架",
????????????????????????"minimum_should_match":?"50%",
????????????????????????"fields":?[
????????????????????????????"name^10",
????????????????????????????"description"
????????????????????????]
????????????????????}
????????????????},
????????????????{
????????????????????"term":?{
????????????????????????"studymodel":?"201001"
????????????????????}
????????????????}
????????????]
????????}
????}
}

JavaAPI

//?搜索方式
//?首先構(gòu)造多關(guān)鍵字查詢條件
MultiMatchQueryBuilder?matchQueryBuilder?=?QueryBuilders.multiMatchQuery("Spring開(kāi)發(fā)框架",?"name",?"description").field("name",?10);
//?然后構(gòu)造精確匹配查詢條件
TermQueryBuilder?termQueryBuilder?=?QueryBuilders.termQuery("studymodel",?"201002");
//?組合兩個(gè)條件,組合方式為?must?全滿足
BoolQueryBuilder?boolQueryBuilder?=?QueryBuilders.boolQuery();
boolQueryBuilder.must(matchQueryBuilder);
boolQueryBuilder.must(termQueryBuilder);
//?將查詢條件封裝給查詢對(duì)象
searchSourceBuilder.query(boolQueryBuilder);

過(guò)濾器

定義過(guò)濾器查詢,是在原本查詢結(jié)果的基礎(chǔ)上對(duì)數(shù)據(jù)進(jìn)行篩選,因此省略了重新計(jì)算的分的步驟,效率更高。并且方便緩存。推薦盡量使用過(guò)慮器去實(shí)現(xiàn)查詢或者過(guò)慮器和查詢共同使用,過(guò)濾器在布爾查詢中使用,下邊是在搜索結(jié)果的基礎(chǔ)上進(jìn)行過(guò)濾:

{
????"query":?{
????????"bool":?{
????????????"must":?[
????????????????{
????????????????????"multi_match":?{
????????????????????????"query":?"spring框架",
????????????????????????"minimum_should_match":?"50%",
????????????????????????"fields":?[
????????????????????????????"name^10",
????????????????????????????"description"
????????????????????????]
????????????????????}
????????????????}
????????????],
????????????"filter":?[
????????????????{
????????????????????//?過(guò)濾條件:studymodel 必須是 201001
????????????????????"term":?{"studymodel":?"201001"}
????????????????},
????????????????{
????????????????????//?過(guò)濾條件:價(jià)格?>=60?<=100
????????????????????"range":?{"price":?{"gte":?60,"lte":?100}}
????????????????}
????????????]
????????}
????}
}

注意:range和term一次只能對(duì)一個(gè)Field設(shè)置范圍過(guò)慮。

JavaAPI

//?首先構(gòu)造多關(guān)鍵字查詢條件
MultiMatchQueryBuilder?matchQueryBuilder?=?QueryBuilders.multiMatchQuery("Spring框架",?"name",?"description").field("name",?10);
//?添加條件到布爾查詢
BoolQueryBuilder?boolQueryBuilder?=?QueryBuilders.boolQuery();
boolQueryBuilder.must(matchQueryBuilder);
//?通過(guò)布爾查詢來(lái)構(gòu)造過(guò)濾查詢
boolQueryBuilder.filter(QueryBuilders.termQuery("studymodel",?"201001"));
boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte(60).lte(100));
//?將查詢條件封裝給查詢對(duì)象
searchSourceBuilder.query(boolQueryBuilder);

排序

我們可以在查詢的結(jié)果上進(jìn)行二次排序,支持對(duì) keyword、date、float 等類型添加排序,text類型的字段不允許排序。排序使用的 JSON 格式如下:

{
????"query":?{
????????"bool":?{
????????????"filter":?[
????????????????{
????????????????????"range":?{
????????????????????????"price":?{
????????????????????????????"gte":?0,
????????????????????????????"lte":?100
????????????????????????}
????????????????????}
????????????????}
????????????]
????????}
????},
????"sort":?[?//?注意這里排序是寫(xiě)在 query key 的外面的。這就表示它的API也不是布爾查詢提供
????????{
????????????"studymodel":?"desc"?//?對(duì)?studymodel(keyword)降序
????????},
????????{
????????????"price":?"asc"?//?對(duì)?price(double)升序
????????}
????]
}

由上面的 JSON 數(shù)據(jù)可以發(fā)現(xiàn),排序所屬的 API 是和 query 評(píng)級(jí)的,因此在調(diào)用 API 時(shí)也應(yīng)該選擇對(duì)應(yīng)的 SearchSourceBuilder 對(duì)象

//?排序查詢
@Test
public?void?testSort()?throws?IOException,?ParseException?{
????//?搜索請(qǐng)求對(duì)象
????SearchRequest?searchRequest?=?new?SearchRequest("ysx_course");
????//?指定類型
????searchRequest.types("doc");
????//?搜索源構(gòu)建對(duì)象
????SearchSourceBuilder?searchSourceBuilder?=?new?SearchSourceBuilder();
????//?搜索方式
????//?添加條件到布爾查詢
????BoolQueryBuilder?boolQueryBuilder?=?QueryBuilders.boolQuery();
????//?通過(guò)布爾查詢來(lái)構(gòu)造過(guò)濾查詢
????boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte(0).lte(100));
????//?將查詢條件封裝給查詢對(duì)象
????searchSourceBuilder.query(boolQueryBuilder);
????//?向搜索請(qǐng)求對(duì)象中設(shè)置搜索源
????searchRequest.source(searchSourceBuilder);
????
????//?設(shè)置排序規(guī)則
????searchSourceBuilder.sort("studymodel",?SortOrder.DESC);?//?第一排序規(guī)則
????searchSourceBuilder.sort("price",?SortOrder.ASC);?//?第二排序規(guī)則
????
????//?執(zhí)行搜索,向ES發(fā)起http請(qǐng)求
????SearchResponse?searchResponse?=?client.search(searchRequest);
????//?搜索結(jié)果
????SearchHits?hits?=?searchResponse.getHits();
????//?匹配到的總記錄數(shù)
????long?totalHits?=?hits.getTotalHits();
????//?得到匹配度高的文檔
????SearchHit[]?searchHits?=?hits.getHits();
????//?日期格式化對(duì)象
????soutData(searchHits);
}

高亮顯示

高亮顯示可以將搜索結(jié)果一個(gè)或多個(gè)字突出顯示,以便向用戶展示匹配關(guān)鍵字的位置。

推薦:Java面試練題寶典

高亮三要素:高亮關(guān)鍵字、高亮前綴、高亮后綴

{
????"query":?{
????????"bool":?{
????????????"must":?[
????????????????{
????????????????????"multi_match":?{
????????????????????????"query":?"開(kāi)發(fā)框架",
????????????????????????"minimum_should_match":?"50%",
????????????????????????"fields":?[
????????????????????????????"name^10",
????????????????????????????"description"
????????????????????????],
????????????????????????"type":?"best_fields"
????????????????????}
????????????????}
????????????]
????????}
????},
????"sort":?[
????????{
????????????"price":?"asc"
????????}
????],
????"highlight":?{
????????"pre_tags":?[
????????????"<em>"
????????],
????????"post_tags":?[
????????????"</em>"
????????],
????????"fields":?{
????????????"name":?{},
????????????"description":?{}
????????}
????}
}

查詢結(jié)果的數(shù)據(jù)如下:

SpringBoot操作ES進(jìn)行各種高級(jí)查詢(值得收藏)

Java 代碼如下,注意到上面的 JSON 數(shù)據(jù), highlight 和 sort 和 query 依然是同級(jí)的,所以也需要用 SearchSourceBuilder 對(duì)象來(lái)設(shè)置到搜索條件中

//?高亮查詢
@Test
public?void?testHighLight()?throws?IOException,?ParseException?{
????//?搜索請(qǐng)求對(duì)象
????SearchRequest?searchRequest?=?new?SearchRequest("ysx_course");
????//?指定類型
????searchRequest.types("doc");
????//?搜索源構(gòu)建對(duì)象
????SearchSourceBuilder?searchSourceBuilder?=?new?SearchSourceBuilder();
????//?搜索方式
????//?首先構(gòu)造多關(guān)鍵字查詢條件
????MultiMatchQueryBuilder?matchQueryBuilder?=?QueryBuilders.multiMatchQuery("Spring框架",?"name",?"description").field("name",?10);
????//?添加條件到布爾查詢
????BoolQueryBuilder?boolQueryBuilder?=?QueryBuilders.boolQuery();
????boolQueryBuilder.must(matchQueryBuilder);
????//?通過(guò)布爾查詢來(lái)構(gòu)造過(guò)濾查詢
????boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte(60).lte(100));
????//?將查詢條件封裝給查詢對(duì)象
????searchSourceBuilder.query(boolQueryBuilder);
?//?***********************
????
????//?高亮查詢
????HighlightBuilder?highlightBuilder?=?new?HighlightBuilder();
????highlightBuilder.preTags("<em>");?//?高亮前綴
????highlightBuilder.postTags("</em>");?//?高亮后綴
????highlightBuilder.fields().add(new?HighlightBuilder.Field("name"));?//?高亮字段
????//?添加高亮查詢條件到搜索源
????searchSourceBuilder.highlighter(highlightBuilder);
????
?//?***********************
????
????//?設(shè)置源字段過(guò)慮,第一個(gè)參數(shù)結(jié)果集包括哪些字段,第二個(gè)參數(shù)表示結(jié)果集不包括哪些字段
????searchSourceBuilder.fetchSource(new?String[]{"name","studymodel","price","timestamp"},new?String[]{});
????//?向搜索請(qǐng)求對(duì)象中設(shè)置搜索源
????searchRequest.source(searchSourceBuilder);
????//?執(zhí)行搜索,向ES發(fā)起http請(qǐng)求
????SearchResponse?searchResponse?=?client.search(searchRequest);
????//?搜索結(jié)果
????SearchHits?hits?=?searchResponse.getHits();
????//?匹配到的總記錄數(shù)
????long?totalHits?=?hits.getTotalHits();
????//?得到匹配度高的文檔
????SearchHit[]?searchHits?=?hits.getHits();
????//?日期格式化對(duì)象
????soutData(searchHits);
}

根據(jù)查詢結(jié)果的數(shù)據(jù)結(jié)構(gòu)來(lái)獲取高亮的數(shù)據(jù),替換原有的數(shù)據(jù):文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-436591.html

private?void?soutData(SearchHit[]?searchHits)?throws?ParseException?{
????SimpleDateFormat?dateFormat?=?new?SimpleDateFormat("yyyy-MM-dd?HH:mm:ss");
????for?(SearchHit?hit?:?searchHits)?{
????????//?文檔的主鍵
????????String?id?=?hit.getId();
????????//?源文檔內(nèi)容
????????Map<String,?Object>?sourceAsMap?=?hit.getSourceAsMap();
????????String?name?=?(String)?sourceAsMap.get("name");

????????//?獲取高亮查詢的內(nèi)容。如果存在,則替換原來(lái)的name
????????Map<String,?HighlightField>?highlightFields?=?hit.getHighlightFields();
????????if(?highlightFields?!=?null?){
????????????HighlightField?nameField?=?highlightFields.get("name");
????????????if(nameField!=null){
????????????????Text[]?fragments?=?nameField.getFragments();
????????????????StringBuffer?stringBuffer?=?new?StringBuffer();
????????????????for?(Text?str?:?fragments)?{
????????????????????stringBuffer.append(str.string());
????????????????}
????????????????name?=?stringBuffer.toString();
????????????}
????????}

????????//?由于前邊設(shè)置了源文檔字段過(guò)慮,這時(shí)description是取不到的
????????String?description?=?(String)?sourceAsMap.get("description");
????????//?學(xué)習(xí)模式
????????String?studymodel?=?(String)?sourceAsMap.get("studymodel");
????????//?價(jià)格
????????Double?price?=?(Double)?sourceAsMap.get("price");
????????//?日期
????????Date?timestamp?=?dateFormat.parse((String)?sourceAsMap.get("timestamp"));
????????System.out.println(name);
????????System.out.println(id);
????????System.out.println(studymodel);
????????System.out.println("你看不見(jiàn)我,看不見(jiàn)我~"?+?description);
????????System.out.println(price);
????}
}

到了這里,關(guān)于SpringBoot操作ES進(jìn)行各種高級(jí)查詢(值得收藏)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包