ElasticSearch的搜索相關(guān)操作
1、基本介紹
Elasticsearch 的查詢是基于 JSON 風(fēng)格的 DSL (Domain Specific Language)來實(shí)現(xiàn)的。
常見的查詢類型包括:
- 查詢所有:查詢出所有數(shù)據(jù),一般測(cè)試用。例如:match_all
- 全文檢索(full text)查詢:利用分詞器對(duì)用戶輸入內(nèi)容分詞,然后去倒排索引庫中匹配。例如:match、multi_match
- 精確查詢:根據(jù)精確詞條值查找數(shù)據(jù),一般查找不分詞的字段,例如keyword、數(shù)值、日期、boolean等類型字段。例如:ids、range、term
- 地理(geo)查詢:根據(jù)經(jīng)緯度查詢,經(jīng)緯度不分詞。例如:geo_distance、geo_bounding_box
- 復(fù)合(compound)查詢:復(fù)合查詢可以將上述各種查詢條件組合起來,合并查詢條件。例如:bool、function_score
下面查詢以以下數(shù)據(jù)為例:
#POST / shopping / _doc / 1001
{
"name": "zhangsan",
"nickname": "zhangsan",
"sex": "男",
"age": 30
}
#POST / shopping / _doc / 1002
{
"name": "lisi",
"nickname": "lisi",
"sex": "男",
"age": 20
}
#POST / shopping / _doc / 1003
{
"name": "wangwu",
"nickname": "wangwu",
"sex": "女",
"age": 40
}
#POST / shopping / _doc / 1004
{
"name": "zhangsan1",
"nickname": "zhangsan",
"sex": "女",
"age": 50
}
#POST / shopping / _doc / 1005
{
"name": "zhangsan2",
"nickname": "zhangsan2",
"sex": "女",
"age": 30
}
2、查詢所有文檔數(shù)據(jù)(match_all)
查找所有文檔內(nèi)容,也可以這樣,向 ES 服務(wù)器發(fā) GET請(qǐng)求 : http://127.0.0.1:9200/shopping/_search,附帶JSON請(qǐng)求體,如下:
{
"query": {
"match_all": {}
}
}
# "query":這里的 query 代表一個(gè)查詢對(duì)象,里面可以有不同的查詢屬性
# "match_all":查詢類型,例如:match_all(代表查詢所有), match,term , range 等等
# {查詢條件}:查詢條件會(huì)根據(jù)類型的不同,寫法也有差異
響應(yīng)結(jié)果:

結(jié)果說明如下:
{
"took【查詢花費(fèi)時(shí)間,單位毫秒】" : 1116,
"timed_out【是否超時(shí)】" : false,
"_shards【分片信息】" : {
"total【總數(shù)】" : 1,
"successful【成功】" : 1,
"skipped【忽略】" : 0,
"failed【失敗】" : 0
},
"hits【搜索命中結(jié)果】" : {
"total"【搜索條件匹配的文檔總數(shù)】: {
"value"【總命中計(jì)數(shù)的值】: 5,
"relation"【計(jì)數(shù)規(guī)則】: "eq" # eq 表示計(jì)數(shù)準(zhǔn)確, gte 表示計(jì)數(shù)不準(zhǔn)確
},
"max_score【匹配度分值】" : 1.0,
"hits【命中結(jié)果集合】" : [
。。。
}
]
}
}
3、精準(zhǔn)查詢
3.1、單關(guān)鍵字單值精準(zhǔn)查詢(term)
term 查詢用于執(zhí)行精確匹配,精確查詢不會(huì)對(duì)查詢條件進(jìn)行分詞,它會(huì)查找指定字段中與查詢值完全匹配的文檔。在 Postman 中,向 ES 服務(wù)器發(fā) GET 請(qǐng)求 :http://127.0.0.1:9200/shopping/_search
{
"query": {
"term": {
"name": {
"value": "zhangsan"
}
}
}
}
查詢結(jié)果:

term 查詢不會(huì)分詞,如果此時(shí)查詢條件是 "zhang" 或者 "san",此時(shí)就無法查出數(shù)據(jù),因?yàn)闆]有 name 為 "zhang" 或 "san" 的數(shù)據(jù)。
(terms 只適合not anynized 即未做分詞的數(shù)據(jù),映射類型為 text(即會(huì)自動(dòng)分詞)的數(shù)據(jù)可能會(huì)被分詞了,用精準(zhǔn)查詢反而可能查不出來。)
3.2、單關(guān)鍵字多值精準(zhǔn)查詢(terms)
terms 查詢和 term 查詢一樣,但它允許你指定一個(gè)字段對(duì)多個(gè)關(guān)鍵字值進(jìn)行匹配。如果該字段包含了多個(gè)關(guān)鍵字中的任何一個(gè)值,那么這個(gè)文檔滿足條件,類似于 mysql 的 in。
在 Postman 中,向 ES 服務(wù)器發(fā) GET 請(qǐng)求 :http://127.0.0.1:9200/shopping/_search,json 請(qǐng)求體如下:
{ "query": { "terms": { "name": ["zhangsan","lisi"] } }}
響應(yīng)結(jié)果:

4、分詞匹配查詢(模糊查詢)
4.1、單字段分詞匹配(match)
match 匹配類型查詢,會(huì)把查詢條件進(jìn)行分詞,然后進(jìn)行查詢,多個(gè)詞條之間是 or 的關(guān)系。
match查詢屬于高層查詢,會(huì)根據(jù)你查詢的字段的類型不一致,采用不同的查詢方式。
- 如果查詢的是日期或者數(shù)值的字段,他會(huì)自動(dòng)將你的字符串查詢內(nèi)容轉(zhuǎn)換成日期或者數(shù)值對(duì)待;
- 如果查詢的內(nèi)容是一個(gè)不能被分詞的字段(keyword),match查詢不會(huì)對(duì)你的指定查詢關(guān)鍵字進(jìn)行分詞;
- 如果查詢的內(nèi)容是一個(gè)可以分詞的字段(text),match會(huì)將你指定的查詢內(nèi)容根據(jù)一定的方式去分詞,然后去分詞庫中匹配指定的內(nèi)容。
總而言之:match查詢,實(shí)際底層就是多個(gè)term查詢,將多個(gè)term查詢的結(jié)果匯集到一起返回給你。
向 ES 服務(wù)器發(fā) GET 請(qǐng)求 :http://127.0.0.1:9200/shopping/_search,請(qǐng)求體為 json 格式,內(nèi)容如下:
{
"query": {
"match": {
"name":"zhangsan"
}
}
}
響應(yīng)結(jié)果如下:

4.2、多字段分詞匹配查詢(multi_match)
multi_match 與 match 類似,不同的是multi_match針對(duì)多個(gè)field進(jìn)行檢索,多個(gè)field對(duì)應(yīng)一個(gè)查詢的關(guān)鍵字。多字段匹配查詢,實(shí)際上是 OR 的關(guān)系,即只要該文檔中有一個(gè)字段匹配到了關(guān)鍵字,就能被查詢出來。
向 ES 服務(wù)器發(fā) GET 請(qǐng)求 :http://127.0.0.1:9200/shopping/_search,請(qǐng)求為 json 格式,內(nèi)容如下:
{
"query": {
"multi_match": {
"query": "zhangsan",
"fields": ["name","nickname"]
}
}
}
響應(yīng)結(jié)果如下:

4.3、短語分詞匹配查詢(match_phrase)
match_phrase 查詢是一種用于匹配短語的查詢方式,它會(huì)將查詢字符串分解成單詞,然后按照順序匹配文檔中的單詞,只有目標(biāo)文檔需要包含分詞后的所有詞,且目標(biāo)文檔中單詞順序與查詢字符串中的單詞順序完全一致時(shí)才會(huì)匹配成功。
match_phrase 與match 都會(huì)進(jìn)行分詞,但不同的是,match查詢只需要匹配查詢中的一個(gè)或多個(gè)單詞即可,而且不需要考慮單詞的順序。例如,如果查詢是“quick brown fox”,match查詢將匹配包含“quick”、“brown”或“fox”的文檔,且不管它們的順序如何。相比之下,match_phrase查詢只會(huì)匹配包含完全短語“quick brown fox”的文檔。
在 Postman 中,向 ES 服務(wù)器發(fā) GET請(qǐng)求 : http://127.0.0.1:9200/shopping/_search,附帶JSON體如下:
{
"query":{
"match":{
"title" : "修改后"
}
}
}
響應(yīng)結(jié)果:

5、模糊查詢
ES 支持多種模糊查詢,包括Wildcard查詢、Fuzzy查詢、Regexp查詢和Match查詢(match 查詢實(shí)際上也是一種模糊查詢)。這些查詢可以用于執(zhí)行模糊匹配、拼寫糾錯(cuò)、范圍查詢等操作。
5.1、Wildcard 查詢(通配符)
Wildcard 查詢是一種基于通配符的查詢,它使用單個(gè)字符(?)代表一個(gè)字符,使用星號(hào)(*)代表零個(gè)或多個(gè)字符。Wildcard 查詢可用于對(duì)單個(gè)詞執(zhí)行模糊匹配,也可以用于對(duì)短語進(jìn)行模糊匹配。它可以在搜索中用于查找某些詞匯的變體或拼寫錯(cuò)誤的單詞。
例如,以下查詢將匹配包含任何以“elasti”開頭的文檔:
GET /my_index/_search
{
"query": {
"wildcard": {
"title": "elasti*"
}
}
}
5.2、Fuzzy 查詢(相似單詞)
Fuzzy 查詢是一種模糊查詢,可以用于查詢包含與搜索字詞相似的字詞的文檔,它可以用于拼寫糾錯(cuò)等操作。
Fuzzy 查詢使用編輯距離算法計(jì)算文本之間的相似度,編輯距離是將一個(gè)術(shù)語轉(zhuǎn)換為另一個(gè)術(shù)語所需的一個(gè)字符更改的次數(shù)。這些更改可以包括:
- 更改字符(box → fox)
- 刪除字符(black → lack)
- 插入字符(sic → sick)
- 轉(zhuǎn)置兩個(gè)相鄰字符(act → cat)
為了找到相似的術(shù)語,fuzzy 在查詢時(shí)會(huì)在指定的編輯距離內(nèi)創(chuàng)建一組搜索詞的所有可能的變體或擴(kuò)展,然后再查詢并返回每個(gè)擴(kuò)展的完全匹配。
以下是一個(gè)使用 Fuzzy 查詢的示例:
GET /my_index/_search
{
"query": {
"fuzzy": {
"title": {
"value": "elasticsearch",
"fuzziness": "AUTO"
}
}
}
}
在上面的示例中,查詢將返回所有與 "elasticsearch" 相似的文檔。Fuzziness 參數(shù)可以指定編輯距離的最大值,它可以是一個(gè)整數(shù),一般可不指定即為 "AUTO" 值,表示 Elasticsearch 將自動(dòng)根據(jù)術(shù)語的長度計(jì)算最佳的編輯距離值。
5.3、Regexp 查詢
Regexp 查詢是一種基于正則表達(dá)式的查詢,它可以用于在文本中查找匹配指定正則表達(dá)式的單詞或短語。Regexp 查詢非常靈活,但由于它需要對(duì)所有文檔進(jìn)行掃描,因此可能會(huì)影響性能。
以下是一個(gè)使用 Regexp 查詢的示例,在下面的示例中,查詢將匹配所有以 "elasticsearch" 開頭的單詞或短語的文檔。
GET /my_index/_search
{
"query": {
"regexp": {
"title": "elasticsearch.*"
}
}
}
6、多條件查詢之must(相當(dāng)于and)
`bool`把各種其它查詢通過`must`(必須 )、`must_not`(必須不)、`should`(應(yīng)該)的方式進(jìn)行組合。
假設(shè)想找出小米牌子,且價(jià)格為3999元的。(must相當(dāng)于數(shù)據(jù)庫的and),在 Postman 中,向 ES 服務(wù)器發(fā) GET請(qǐng)求 : http://127.0.0.1:9200/shopping/_search,附帶JSON體如下:
{
"query":{
"bool":{
"must":[{
"match":{
"category":"小米"
}
},{
"match":{
"price":3999.00
}
}]
}
}
}
7、多條件查詢之should(相當(dāng)于or)
假設(shè)想找出小米或華為的牌子。(should相當(dāng)于數(shù)據(jù)庫的||),在 Postman 中,向 ES 服務(wù)器發(fā) GET請(qǐng)求 : http://127.0.0.1:9200/shopping/_search,附帶JSON體如下:
{
"query":{
"bool":{
"should":[{
"match":{
"category":"小米"
}
},{
"match":{
"category":"華為"
}
}]
},
"filter":{
"range":{
"price":{
"gt":2000
}
}
}
}
}
8、范圍查詢(range)
range 查詢找出那些落在指定區(qū)間內(nèi)的數(shù)字或者時(shí)間。range 查詢?cè)试S以下字符:

假設(shè)想找出小米或華為的牌子,且價(jià)格大于2000元的手機(jī)。在 Postman 中,向 ES 服務(wù)器發(fā) GET請(qǐng)求 : http://127.0.0.1:9200/shopping/_search,附帶JSON體如下:
{
"query":{
"bool":{
"should":[{
"match":{
"category":"小米"
}
},{
"match":{
"category":"華為"
}
}],
"filter":{
"range":{
"price":{
"gt":2000
}
}
}
}
}
}
9、分頁查詢(from、size)
向 ES 服務(wù)器發(fā) GET請(qǐng)求 : http://127.0.0.1:9200/shopping/_search,附帶JSON體如下:
{
"query":{
"match_all":{}
},
"from": 2, //碼數(shù)索引,從0開始。如2,即表示從第3條開始,查詢size條
"size":2
}
10、查詢排序(sort)
如果你想通過排序查出價(jià)格最高的手機(jī),向 ES 服務(wù)器發(fā) GET請(qǐng)求 : http://127.0.0.1:9200/shopping/_search,附帶JSON體如下:
{
"query":{
"match_all":{}
},
"sort":{
"price":{
"order":"desc"
}
}
}
11、高亮查詢(highlight)
在 Postman 中,向 ES 服務(wù)器發(fā) GET請(qǐng)求 : http://127.0.0.1:9200/shopping/_search,附帶JSON體如下:
{
"query":{
"match_phrase":{
"category" : "為"
}
},
"highlight":{
"fields":{
"category":{}//<----高亮這字段
}
}
}
返回結(jié)果如下:

12、聚合查詢
聚合允許使用者對(duì) es 文檔進(jìn)行統(tǒng)計(jì)分析,類似與關(guān)系型數(shù)據(jù)庫中的 group by,當(dāng)然還有很多其他的聚合,例如取最大值、平均值等等。
12.1、取最大值(max)
在 Postman 中,向 ES 服務(wù)器發(fā) GET請(qǐng)求 : http://127.0.0.1:9200/shopping/_search,附帶JSON體如下:
{ "aggs": { "max_age": { "max": { "field": "age" } } }, "size": 0 }
返回結(jié)果如下:

12.2、取最小值(min)
在 Postman 中,向 ES 服務(wù)器發(fā) GET請(qǐng)求 : http://127.0.0.1:9200/shopping/_search,附帶JSON體如下:
{ "aggs": { "min_age": { "min": { "field": "age" } } }, "size": 0 }
返回結(jié)果如下:

12.3、對(duì)字段值求和(min)
在 Postman 中,向 ES 服務(wù)器發(fā) GET請(qǐng)求 : http://127.0.0.1:9200/shopping/_search,附帶JSON體如下:
{ "aggs": { "sum_age": { "sum": { "field": "age" } } }, "size": 0 }
返回結(jié)果如下:

12.4、對(duì)字段值取平均值(avg)
在 Postman 中,向 ES 服務(wù)器發(fā) GET請(qǐng)求 : http://127.0.0.1:9200/shopping/_search,附帶JSON體如下:
{ "aggs": { "avg_age": { "avg": { "field": "age" } } }, "size": 0 }
返回結(jié)果如下:

12.5、對(duì)字段去重后取數(shù)量(distinct)
在 Postman 中,向 ES 服務(wù)器發(fā) GET請(qǐng)求 : http://127.0.0.1:9200/shopping/_search,附帶JSON體如下:
{ "aggs": { "distinct_age": { "cardinality": { "field": "age" } } }, "size": 0 }
返回結(jié)果如下:

12.6、State 聚合(包含count,max,min,avg 和 sum)
State 聚合會(huì)一次性返回指定字段的count,max,min,avg 和 sum五個(gè)指標(biāo)的數(shù)據(jù)。
在 Postman 中,向 ES 服務(wù)器發(fā) GET請(qǐng)求 : http://127.0.0.1:9200/shopping/_search,附帶JSON體如下:
{ "aggs": { "stats_age": { "stats": { "field": "age" } } }, "size": 0 }
返回結(jié)果如下:

12.7、分組求數(shù)量(group by)
在 Postman 中,向 ES 服務(wù)器發(fā) GET請(qǐng)求 : http://127.0.0.1:9200/shopping/_search,附帶JSON體如下:
在 terms 分組下再進(jìn)行聚合:
{ "aggs": { "age_groupby": { "terms": { "field": "age" } } }, "size": 0 }
返回結(jié)果如下:


浙公網(wǎng)安備 33010602011771號(hào)