Elasticsearch系列---實戰搜尋語法
概要
本篇介紹Query DSL的語法案例,查詢語句的除錯,以及排序的相關內容。
基本語法
空查詢
最簡單的搜尋命令,不指定索引和型別的空搜尋,它將返回叢集下所有索引的所有文件(預設顯示10條):
GET /_search
{}
搜尋多個索引
GET /index1,index2/_doc/_search
{}
指定分頁搜尋
GET /_search
{
"from": 0,
"size": 10
}
get帶request body
HTTP協議,GET請求帶body是不規範的做法,但由於ES搜尋的複雜性,加上HTTP協議GET/POST方法表述的語義,GET更適合用來表述查詢的動作,雖然不規範,但還是這麼用了。現在大多數瀏覽器也支援GET+request body,如果遇到不支援的,換成POST即可。瞭解一下就行,不用太慌張。
查詢表示式Query DSL
Query DSL是一種非常靈活、可讀性高的查詢語言,body為JSON格式,絕大部分功能都可以用它來展現,並且這種查詢語句更純粹,讓學習者更專注於本身的功能,避免Client API的干擾。
上一節的空查詢,等價於這個:
GET /_search
{
"query": {
"match_all": {}
}
}
基本語法
# 查詢語句結構 { QUERY_NAME: { ARGUMENT: VALUE, ARGUMENT: VALUE,... } } # 針對某個欄位的查詢 { QUERY_NAME: { FIELD_NAME: { ARGUMENT: VALUE, ARGUMENT: VALUE,... } } }
合併查詢語句
再複雜的查詢語句,也是由一個一個的查詢條件疊加而成的,查詢語句有兩種形式:
- 葉子語句:單個條件組成的語句,如match語句,類似mysql的"id = 1"這種。
- 複合語句:有多個條件,需要合併在一起才能組成一個完整的語句,需要使用bool進行組合,裡面的條件可以用must必須匹配、must not必須不匹配、should可以匹配修飾,也可以包含過濾器filter。類似mysql的"(status = 1 && language != 'french' && (author = 'John' || author = 'Tom'))"這種。
舉個例子:
{
"bool": {
"must": { "match": { "status": 1 }},
"must_not": { "match": { "language": "french" }},
"should": { "match": { "author": "John Tom" }},
"filter": { "range": { "length" : { "gt" : 30 }} }
}
}
複合語句可以巢狀,來實現更復雜的查詢需求,在上面的例子上簡單延伸一下:
"bool": {
"must": { "match": { "status": 1 }},
"must_not": { "match": { "language": "french" }},
"should": [
{"match": { "author": "John Tom" }},
{"bool": {
"must": { "match": { "name": "friend" }},
"must_not": { "match": { "content": "star" }}
}}
],
"filter": { "range": { "length" : { "gt" : 30 }} }
}
複合語句相關性分數計算
每一個子查詢都獨自地計算文件的相關性得分。一旦他們的得分被計算出來,bool 查詢就將這些得分進行合併並且返回一個代表整個布林操作的得分,得分高的顯示在前面,filter內的條件不參與分數計算。
過濾器filter
我們還是以英文兒歌的索引為案例,看一個搜尋需求:歌詞內容包含friend,同時歌長大於30秒的記錄
GET /music/children/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"content": "friend"
}
}
],
"filter": {
"range": {
"length": {
"gte": 30
}
}
}
}
}
}
filter與query
- 過濾情況filtering context
僅按照搜尋條件把需要的資料篩選出來,不計算相關度分數。
- 查詢情況query context
匹配條件的資料,會根據搜尋條件的相關度,計算每個document的分數,然後按照分數進行排序,這個才是全文搜尋的情況。
效能差異
filter只做過濾,不作排序,並且會快取結果到記憶體中,效能非常高。
query匹配條件,要做評分,沒有快取,效能要低一些。
應用場景
filter一個非常重要的作用就是減少不相關資料對query的影響,提升query的效能,二者常常搭配在一起使用。
組合使用的時候,把期望符合條件的document的搜尋條件放在query裡,把要濾掉的條件放在filter裡。
constant_score查詢
如果一個查詢只有filter過濾條件,可以用constant_score來替代bool查詢,這樣的查詢語句更簡潔、更清晰,只是沒有評分,示例如下:
GET /music/children/_search
{
"query": {
"constant_score": {
"filter": {
"term": { "content": "gymbo"}
}
}
}
}
filter內不支援terms語法,注意一下。
最常用的查詢
再複雜的查詢語句,也是由最基礎的查詢變化而來的,而最常用的查詢其實也就那麼幾個。
- match_all查詢
查詢簡單的匹配所有文件
GET /_search
{
"query": {
"match_all": {}
}
}
- match查詢
無論是全文搜尋還是精確查詢,match查詢是最基本的標準
# 全文搜尋例子
{ "match": { "content": "loves smile" }}
# 精確搜尋
{ "match": { "likes": 15 }}
{ "match": { "date": "2019-12-05" }}
{ "match": { "isOwner": true }}
{ "match": { "keyword": "love you" }}
對於精確值的查詢,我們可以使用filter來替代,filter有快取的效果。
- multi_match查詢
可以在多個欄位上執行相同的match查詢
{
"multi_match": {
"query": "my sunshine",
"fields": [ "name", "content" ]
}
}
- range查詢
查詢指定區間內的數字或時間,query和filter都支援,一般是filter用得多,允許的操作符如下:
- gt 大於
- gte 大於或等於
- lt 小於
- lte 小於或等於
{
"range": {
"length": {
"gte": 45,
"lt": 60
}
}
}
- term查詢
用於精確值匹配,精確值可以是數字,日期,boolean或keyword型別的字串
{ "term": { "likes": 15 }}
{ "term": { "date": "2019-12-05" }}
{ "term": { "isOwner": true }}
{ "term": { "keyword": "love you" }}
建立索引時mapping設定為not_analyzed時,match等同於term,用得多的是match和range。
- terms查詢
跟term類似,只是允許一次指定多個值進行匹配,只要有任何一個匹配上,都滿足條件
{ "terms": { "content": [ "love", "gymbo", "sunshine" ] }}
查詢語句除錯
複雜的查詢語句,可能會有幾百行,可以先使用除錯工具檢測一下查詢語句,定位不合法的搜尋及原因,完整語法如下:
GET /index/type/_validate/query?explain
{
"query": {
...
}
}
explain引數可以提供更詳細的查詢不合法的資訊,便於問題定位。寫一個錯誤的例子,比如使用中文標點符號:
GET /music/children/_validate/query?explain
{
"query": {
"terms": { "content“: [ "love", "gymbo", "sunshine" ] }
}
}
錯誤提示如下:
{
"valid": false,
"error": """
ParsingException[Failed to parse]; nested: JsonParseException[Unexpected character ('l' (code 108)): was expecting a colon to separate field name and value
at [Source: org.elasticsearch.transport.netty4.ByteBufStreamInput@5e57280e; line: 3, column: 33]];; com.fasterxml.jackson.core.JsonParseException: Unexpected character ('l' (code 108)): was expecting a colon to separate field name and value
at [Source: org.elasticsearch.transport.netty4.ByteBufStreamInput@5e57280e; line: 3, column: 33]
"""
}
valid關鍵字,true為驗證通過,false為不通過,如上提示資訊,會指明3行33列錯誤,原因是使用了中文的引號。將語法修正後,得到的正確響應如下:
{
"_shards": {
"total": 1,
"successful": 1,
"failed": 0
},
"valid": true,
"explanations": [
{
"index": "music",
"valid": true,
"explanation": "+content:(gymbo love sunshine) #*:*"
}
]
}
排序
查詢請求得到的結果,預設排序是相關性得分降序。如果我們只使用filter過濾,符合filter條件的文件,評分都是一樣的(bool的filter得分是null,constant_score得分是1),結果文件還是隨機返回,顯然這樣的排序不符合我們的預期。
sort排序規則
為此,我們可以使用sort屬性,對文件進行排序,sort的用法與mysql如出一轍,示例如下:
GET /music/children/_search
{
"query": {
"bool": {
"filter": { "range": { "length" : { "gt" : 30 }} }
}
},
"sort": [
{
"length": {
"order": "desc"
}
}
]
}
sort內可以同時指定多個排序欄位,一旦使用sort排序後,_score得分將變成null,因為我們指定了排序規則,_score沒有實際意義了,就不用耗費精力再去計算它。
字串排序問題
我們知道text型別的欄位,會有關鍵詞分詞處理,對這樣的欄位進行排序,結果往往都不準確,6.x版本以後的text型別,會再自動建立一個keyword型別的欄位,這個欄位是不分詞的,所以這樣就有了分工,text型別的負責搜尋,keyword型別則負責排序。
我們回顧一下music索引的mapping資訊(節選):
{
"music": {
"mappings": {
"children": {
"properties": {
"content": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
}
}
}
}
例如name欄位,有一個text型別的,裡面fields還有一個型別為keyword,名稱也為keyword的欄位,所以在排序的場景中,我們應該使用name.keyword,示例如下:
GET /music/children/_search
{
"sort": [
{
"name.keyword": {
"order": "asc"
}
}
]
}
小結
本篇介紹Query DSL的語法及基礎實戰內容,順帶點了一下filter與query的區別,面對複雜查詢語句時,建議先用驗證工具進行排查,最後介紹了一下排序方面的知識,基礎語法、上機案例多實踐即可。
專注Java高併發、分散式架構,更多技術乾貨分享與心得,請關注公眾號:Java架構社群
相關推薦
Elasticsearch系列---實戰搜尋語法
概要 本篇介紹Query DSL的語法案例,查詢語句的除錯,以及排序的相關內容。 基本語法 空查詢 最簡單的搜尋命令,不指定索引和型別的空搜尋,它將返回叢集下所有索引的所有文件(預設顯示10條): GET /_search {} 搜尋多個索引 GET /index1,index2/_doc/_search {
Elasticsearch系列---初識搜尋
概要 本篇主要介紹搜尋的報文結構含義、搜尋超時時間的處理過程,提及了一下多索引搜尋和輕量搜尋,最後將精確搜尋與全文搜尋做了簡單的對比。 空搜尋 搜尋API最簡單的形式是不指定索引和型別的空搜尋,它將返回叢集下所有索引的所有文件(預設顯示10條): GET /_search 響應的結果示例(有篩選,只取了一條d
ElasticSearch最佳入門實踐(四十九)各種query搜尋語法
1、match all 查詢所有 GET /_search { "query": { "match_all": {} } } 2、match 匹配某一個filed是否包含文字 GET /_search {
搜尋推薦一——Centos搭建Elasticsearch單機實戰
環境 jdk: 1.8 centos: 7 elasticsearch: 5.3.0 一、JDK安裝 $: tar -zxvf jdk-8u181-linux-x64.tar.gz $: mkdir /usr/local/java $: cp jdk1.8
ElasticSearch最佳入門實踐(四十七)query DSL搜尋語法
1、一個例子讓你明白什麼是Query DSL GET /_search { "query": { "match_all": {} } } 2、Query DSL的基本語
ElasticSearch36:初識搜尋引擎_快速上機動手實戰Query DSL搜尋語法
1.match allGET /website/article/_search { "query": { "match_all": {} } } 執行結果:{ "took": 38, "timed_out": false, "_shards":
elasticsearch核心知識--38.Query DSL搜尋語法和bool多條件查詢
1、一個例子讓你明白什麼是Query DSLGET /_search{ "query": { "match_all": {} }}2、Query DSL的基本語法{ QUERY_NAME: { ARGUMENT: VALUE,
elasticsearch系列四:搜尋詳解(搜尋API、Query DSL)
{ "took": 60, "timed_out": false, "_shards": { "total": 5, "successful": 5, "skipped": 0, "failed": 0 }, "hits": { "total": 1000, "m
第十三篇 elasticsearch的Query DSL搜尋語法
Query DSL基本語法 { QUERY_NAME: { ARGUMENT: VALUE, ARGUMENT: VALUE,... } } { QUERY_NAME: { FIELD_
elasticsearch-驗證搜尋語法是否正確
【問題描述】:驗證拼寫的查詢語句是否正確,在/索引/型別後使用_validate/query?explain:GET /test_index/test_type/_validate/query?explain{ "query": { "math": { "t
Elasticsearch系列---搜尋執行過程及scroll遊標查詢
概要 本篇主要介紹一下分散式環境中搜索的兩階段執行過程。 兩階段搜尋過程 回顧我們之前的CRUD操作,因為只對單個文件進行處理,文件的唯一性很容易確定,並且很容易知道是此文件在哪個node,哪個shard中。 但搜尋比CRUD複雜,符合搜尋條件的文件,可能散落在各個node、各個shard中,我們需要找到匹配
Elasticsearch系列---結構化搜尋
概要 結構化搜尋針對日期、時間、數字等結構化資料的搜尋,它們有自己的格式,我們可以對它們進行範圍,比較大小等邏輯操作,這些邏輯操作得到的結果非黑即白,要麼符合條件在結果集裡,要麼不符合條件在結果集之外,沒有那種相似的概念。 前言 結構化搜尋將會有大量的搜尋例項,我們將"音樂APP"作為主要的案例背景,去開發一
Elasticsearch系列---深入全文搜尋
概要 本篇介紹怎樣在全文欄位中搜索到最相關的文件,包含手動控制搜尋的精準度,搜尋條件權重控制。 手動控制搜尋的精準度 搜尋的兩個重要維度:相關性(Relevance)和分析(Analysis)。 相關性是評價查詢條件與結果的相關程度,並對相關程度進行排序,一般使用TF/IDF方法。 分析是指將索引文件與查詢條
Elasticsearch系列---多欄位搜尋
### 概要 本篇介紹一下multi_match的best_fields、most_fields和cross_fields三種語法的場景和簡單示例。 ### 最佳欄位 bool查詢採取"more-matches-is-better"匹配越多分越高的方式,所以每條match語句的評分結果會被加在一起,從而
elasticsearch系列(四)部署
linux .tar.gz ast 官方 hup bin arc 分享 quest linux環境 centOS6.8 本文采用tar包的方式部署es 準備jdk8的環境 5.4.0的es依賴jdk8及以上版本 下載linux版的jdk jdk-8u121-linux-x6
搜索引擎ElasticSearch系列(四): ElasticSearch2.4.4 sql插件安裝
china code als 插件 技術分享 -s fun nlp 4.0 一:ElasticSearch sql插件簡介 With this plugin you can query elasticsearch using familiar SQL syntax.
elasticsearch系列(六)備份
indices stat 必須 tor 信息 操作 accepted gui 配置 快照備份 1.創建文件倉庫 1.1 在$ELASTICSEARCH_HOME/config/elasticsearch.yaml中增加配置 #這個路徑elasticsearch必須有權限訪問
elasticsearch系列(七)java定義score
集群 scrip image search 支持 name dsr 計算方法 dynamic 概述 ES支持groovy 和 java兩種語言自定義score的計算方法,groovy甚至可以嵌套在請求的參數中,有點厲害,不過不在本篇討論範圍。 如何用自定義的java代碼來定
java開發實戰之語法篇
java11.271,錯誤信息與標準信息的輸出標準信息輸出流out(黑色)錯誤信息輸出流err(紅色)package conn.cev.yufa;public class yufa { public static void main(String[] args) { System.out.println(&
ElasticSearch 系列隨筆
www 錯誤 問題 day last del home AI 插入 1.ElasticSearch 常用設置 2.ElasticSearch 從2.2升級到6.2.4後在Kibana註意問題 (Validation Failed: 1: an id must be pro