ES 查詢語法解析之SearchAPI - 文章很長,慎入

本文以6.8版本為例

1. 搜索API(_search API)

下面的地址可以找到很多版本的參考文檔:
https://www.elastic.co/guide/en/elasticsearch/reference/index.html

搜索的端點地址可以是多索引多mapping type的。搜索的參數可作為URI請求參數給出,也可用request body給出。

  • 搜索API端點地址(6.8版本)


GET /bank/account/_search
GET /twitter/ _search?q=user:kimchy
GET /kimchy,elasticsearch/_search?q=tag:wow
GET /_all/_search?q=tag:wow
GET /_search?q=tag:wow

1.search

# 指定index
GET /bank/_search?q=address:bristol

# 查詢多個索引
GET /bank,songs_v1/_search

# 查詢所有
GET /_all/_search

# 查詢所有
GET /_search

2. URL Search


這里還可以點擊Copy as curl查看另外的一種訪問形式,當然上邊的語句中也有描述:
but it can be handy for quick "curl tests".
此時粘貼到nodepad等編輯器中的顯示結果如下:
curl -X GET "localhost:9200/twitter/_search?q=user:kimchy&pretty"
這個指令可以直接在linux中執行,很方便進行測試

對上面的返回內容進行簡單的解釋:

{
   "timed_out": false,  #是否超時
   "took": 62,  # 本次查詢消耗的時間,這里是62ms
   "_shards":{ # 分片相關的內容
       "total" : 1, # 總共有多少個分片
       "successful" : 1, # 成功查詢了多少個分片
       "skipped" : 0, # 跳過了多少個分片
       "failed" : 0 # 有多少個分片是失敗的
   },
   "hits":{ # 查詢命中的信息
       "total" : 1, # 總共命中的數量
       "max_score": 1.3862944, # 所有命中中的最高得分,因為這里只有一個命中,所以得分等于該命中的內容
       "hits" : [ # 所有命中的文檔所組成的一個數組
           {
               "_index" : "twitter",  # 屬于哪個index
               "_type" : "_doc", # 是什么類型的type
               "_id" : "0", # id 是多少
               "_score": 1.3862944, # 命中得分
               "_source" : {  # source字段
                   "user" : "kimchy",
                   "date" : "2009-11-15T14:12:12",
                   "message" : "trying out Elasticsearch",
                   "likes": 0
               }
           }
       ]
   }
}

相關的parameters,這里僅羅列了一些,具體可以到網站上進行查詢:


3. Request Body Search


From/Size:分頁相關,但是不建議使用,原因如下:
因為在有分片的情況下,需要先查詢每個分片上的內容之后合并然后再符合的內容,比方說一共有5個分片,當查詢前10的時候需要分別查詢5個分片的前10(因為其分布情況是未知的,所以我們只能這樣查詢),歸整排序后再選擇前面的10個,這好像也沒有什么問題,但是如果取11~20的時候呢? 這個時候就需要5個分片分別取20個,然后歸整,最后取11~20中的內容。所以這里我們就發現問題了,在不斷往后去取數據的時候,五個分片導致的后果就是要查詢的內容不斷擴大,本質上效率沒有提升反而下降了。

官網的建議是 批量的時候使用Scorll(不適合交互式查詢),其他的時候使用Search After
使用的例子:

#  From/Size分頁相關
GET /bank/_search
{
 "sort": [
   {
     "account_number": {
       "order": "asc"
     }
   }
 ],
 "from": 0,"size": 10
}

Search After: 分頁相關,解決from/size的相關問題


例子:

# 分頁相關 Search After
GET /bank/_search
{
  "size": 6,
  "sort": [
    {
      "account_number": {
        "order": "asc"
      }
    }
  ]
}


GET /bank/_search
{
  "size": 6,
  "sort": [
    {
      "account_number": {
        "order": "asc"
      }
    }
  ],
  "search_after": [1]
}

但是這個方法也有一定的問題,比如排序的字段內容最好都是唯一的,不然可能會導致某些數據無法查詢到,比如如果返回的排序數字是 10, 但是排序的字段為10的內容條數過多,比如第一次是查詢10條內容,最后一條的排序字段的數字是10,而其后邊還有很多個數字為10的內容,那么下一次在發送查詢的時候,由于search_after填寫的是10,那么這些沒有羅列出來的10的內容,就被跳過了。

Field Collapsing: 字段折疊


例子:

# field collapse
GET /bank/_search
{
 "query": {
   "match": {
     "address": "street"
   }
 }, 
 "collapse": {
   "field": "gender.keyword"
 }
}

# 將數據展開
GET /bank/_search
{
 "query": {
   "match": {
     "address": "street"
   }
 }, 
 "collapse": {
   "field": "gender.keyword",
   "inner_hits" : {
     "name": "details",
     "size": 3,
     "sort": ["account_number"]
   }
 }
}

# 多次折疊
GET /bank/_search
{
 "query": {
   "match": {
     "address": "street"
   }
 },
 "collapse": {
   "field": "gender.keyword",
   "inner_hits": {
     "name": "age_coll",
     "collapse": {"field": "age"},
     "size": 3
   }
 }
}

Source filtering: source 過濾


例子:

# _source
# 展示(默認是true)
GET /bank/_search
{
 "query": {
   "match_all": {}
 },
 "_source": true
}

# 隱藏
GET /bank/_search
{
 "query": {
   "match_all": {}
 },
 "_source": false
}

# 指定返回的內容
GET /bank/_search
{
 "query": {
   "match_all": {}
 },
 "_source": ["address", "balance"]
}

# 返回指定的內容以外的內容
GET /bank/_search
{
 "query": {
   "match_all": {}
 },
 "_source": {
   "excludes": ["address", "balance"]
 }
}

# includes,本質與返回指定內容一樣
GET /bank/_search
{
 "query": {
   "match_all": {}
 },
 "_source": {
   "includes": ["address", "balance"]
 }
}

Fields


例子:

#stored_fields 

#對于非store字段,沒有任何意義

PUT /songs_v20
PUT /songs_v20/_mapping/classic
{
 "properties": {
   "songName" : {"type": "text"},
   "singer" : {"type": "keyword"},
   "lyrics" : {
     "type": "text",
     "store": true
   }
 }
}

POST /songs_v20/classic
{
 "songName" : "could this be love",
 "singer" : "James",
 "lyrics" : "Could This Be love,Woke Up This Morning Just Sat In My Bed,8 a.m. First Thing In My Head,Is A Certain Someone Who's Always On My Mind,He Treats Me"
}


GET /songs_v20/_search
{
 "_source": true,
 "query": {
   "match_all": {}
 },
 "stored_fields": ["songName", "singer", "lyrics"]
}

Version: 是否返回版本信息


例子:

#   version 是否返回版本信息

GET /bank/account/_search
{
 "query": {
   "term": {
     "_id": {
       "value": "20"
     }
   }
 },
 "version": true
}

Script Fields: 將字段計算后返回


例子:

# script field 將字段計算后返回
GET /bank/_search
{
 "_source": true,
 "query": {
   "term": {
     "_id": {
       "value": "20"
     }
   }
 },
 "script_fields": {
   "age_2year_later": {
     "script" : {
       "lang": "painless",
      "source" : "doc['age'].value + 2"
     }
   },
   "age_2year_before" : {
     "script" : {
       "lang": "painless",
      "source" : "doc['age'].value - 2"
     }
   }
 }
}

min_score: 過濾掉評分太低的


例子:

#有評分太低的,
GET /songs_v1/popular/_search
{
 "query": {
   "match": {
     "lyrics": "So many people all around the world"
   }
 }
}

#加上min_score 去掉評分低的
GET /songs_v1/_search
{
 "query": {
   "match": {
     "lyrics": "so many people all around world"
   }
 },
 "min_score" : 1
}

Sort:排序


例子:

# sort
GET /bank/_search?size=4
{
 "_source": false,
 "query": {
   "term": {
     "state.keyword": {
       "value": "DC"
     }
   }
 },
 "sort": [
   {
     "age": {
       "order": "asc"
     }
   }
 ]
}

# sort mode

# min max avg
GET /numbers/_search
{
 "sort": [
   {
     "numbers": {
       "order": "desc",
       "mode": "min"
     }
   }
 ]
}


# 按照數組的長度來排序的實現方式
GET /numbers/_search
{
 "sort": [
   {
     "scriptFIELD": {
       "type": number,
       "script": {
         "lang": "painless",
         "source": "doc['numbers'].length"
       },
       "order": "desc"
     }
   }
 ]
}

Highlighting: 高亮


例子:

高亮

GET /bank/_search
{
 "query": {
   "match": {
     "address": "green"
   }
 },
 "highlight": {
   "fields": {
     "address": {}
   }
 }
}
#當我們指定需要高亮顯示時,返回結果時,就會在與搜索內容匹配的地方包裹一個標簽

#這個標簽是可以替換掉的
GET /bank/_search
{
 "query": {
   "match": {
     "address": "green"
   }
 },
 "highlight": {
   "fields": {
     "address": {
       "pre_tags": "<strong>",
       "post_tags": "</strong>"
     }
   }
 }
}

如果覺得有收獲就點個贊吧,更多知識,請點擊關注查看我的主頁信息哦~

?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,533評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,055評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,365評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,561評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,346評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,889評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,978評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,118評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,637評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,558評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,739評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,246評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,980評論 3 346
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,362評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,619評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,347評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,702評論 2 370

推薦閱讀更多精彩內容