Elasticsearch-05Elasticsearch之查询与过滤
文章目錄
- 官方API文檔
- 準備數據
- 請求體查詢
- 空查詢
- from 及 size 參數進行分頁
- 結構化查詢
- 查詢子句
- 合并多子句
- 查詢與過濾
- 查詢語句與過濾語句的區別
- Query DSL
- match_all 查詢
- match 查詢
- multi_match 查詢
- bool 查詢
- Filter DSL
- term 過濾
- terms 過濾
- range 過濾
- exists 和 missing 過濾
- bool 過濾
- 查詢與過濾條件的合并
- 帶過濾的查詢語句
- 單條過濾語句
- 驗證查詢 (_validate)
- 查看錯誤信息
- 查看ES如何執行的
官方API文檔
當前版本 7.0 : https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html
5.6的版本的: https://www.elastic.co/guide/en/elasticsearch/reference/5.6/index.html
準備數據
新建索引 book
{"settings":{"number_of_shards":3,"number_of_replicas":1},"mappings":{"novel":{"properties":{"word_count":{"type":"integer"},"author":{"type":"keyword"},"title":{"type":"text"},"publish_date":{"type":"date","format":"yyyy-MM-dd HH:mm:ss || yyyy-MM-dd || epoch_millis"}}}} }新增數據
多增加幾條數據
再增加個artisan 索引
請求體查詢
空查詢
GET /_search將會返回所有索引中所有的文檔
可以查詢一個, 多個或 _all 索引(indices)或類型(types) ,index支持通配符
GET /b*k/type1,type2/_search將會返回指定查詢條件的文檔
POST http://localhost:9200/*k/novel/_search
from 及 size 參數進行分頁
GET /_search { "from": 30, "size": 10 }Get請求也能攜帶參數? 是不是很別扭? 因為攜帶交互數據的 GET 請求并不被廣泛支持, 所以 search API同樣支持 POST 請求, 類似于這樣:
POST /_search { "from": 30, "size": 10 }這個原理同樣應用于其他攜帶交互數據的 GET API請求中
POST http://localhost:9200/book/novel/_search
結構化查詢
結構化查詢Query DSL是一種靈活的, 多表現形式的查詢語言。 Elasticsearch在一個簡單的JSON接口中用結構化查詢來展現Lucene的絕大多數能力, 使用DSL查詢能夠讓查詢更加靈活, 精準, 易于閱讀并且易于debug。
使用結構化查詢, 需要query 參數
GET /_search { "query": YOUR_QUERY_HERE }空查詢 - {} - 在功能上等同于使用 match_all 查詢子句, 正如其名字一樣, 匹配所有的文檔
POST http://localhost:9200/book/novel/_search
查詢子句
語法如下:
{QUERY_NAME: {ARGUMENT: VALUE,ARGUMENT: VALUE,...} }或指向一個指定的字段
{QUERY_NAME: {FIELD_NAME: {ARGUMENT: VALUE,ARGUMENT: VALUE,...}} }舉個例子: 使用 match 查詢子句用來找尋在 title字段中找尋包含 elasticsearch 的成員
{"match": {"title": "Elasticsearch"} }完整的查詢請求如下
必須使用query關鍵字 , url中必須使用_search
POST http://localhost:9200/book/novel/_search
合并多子句
查詢子句就像是搭積木一樣, 可以合并簡單的子句為一個復雜的查詢語句。
- 簡單子句(leaf clauses)(比如 match 子句)用以在將查詢字符串與一個字段(或多字段)進行比較
- 復合子句(compound)用以合并其他的子句。 例如, bool 子句允許你合并其他的合法子句, 無論是 must , must_not 還是 should .
- 復合子句可以合并多種子句為一個單一的查詢, 無論是簡單子句還是其他的復合子句
在關系型數據庫中有很多條件判斷,比如 等于= 不等于!= ,或者 or ,在es中
- must 需要滿足條件 ==或like
- must_not 不需要在滿足條件內的 !=或 not like
- should: should中的兩個條件至少滿足一個就可以,should下有多個條件時注意加參數 minimum_should_match
舉個例子,查找 title包含Elasticsearch ,并且作者不能為李四的記錄
{"query":{"bool":{"must":{"match":{"title":"Elasticsearch"}},"must_not":{"match":{"author":"李四"}}}} }POST http://localhost:9200/book/novel/_search
查詢與過濾
查詢與過濾語句非常相似, 但是它們由于使用目的不同而稍有差異。
一條過濾語句會詢問每個文檔的字段值是否包含著特定值, 比如 是否 createTime 的日期范圍某個時間段內? 是否 status 字段中包含單詞 “published” ?
查詢語句與過濾語句的區別
- Query查詢語句會詢問每個文檔的字段值與特定值的匹配程度如何,ES會給出一個相關性評分 _score , 并且 按照相關性對匹配到的文檔進行排序。 這種評分方式非常適用于一個沒有完全配置結果的全文本搜索。
- Query查詢語句不僅要查找相匹配的文檔, 還需要計算每個文檔的相關性, 所以一般來說查詢語句要比過濾語句更耗時, 并且查詢結果也不可緩存
- Filter過濾查詢語句在查詢過程中,只判斷該文檔是否滿足條件,只有yes和no。用作過濾不用做模糊查詢. 對fifter es會用緩存,相對query來說會更快
原則上來說, 使用查詢語句做全文本搜索或其他需要進行相關性評分的時候, 剩下的全部用過濾語句
Query DSL
match_all 查詢
使用 match_all 可以查詢到所有文檔, 是沒有查詢條件下的默認語句
POST http://localhost:9200/book/novel/_search
{"query":{"match_all":{}} }match 查詢
match 查詢是一個標準查詢, 不管你需要全文本查詢還是精確查詢基本上都要用到它。
如果你使用 match 查詢一個全文本字段, 它會在真正查詢之前用分析器先分析 match 一下查詢字符:
POST http://localhost:9200/book/novel/_search
{"query":{"match":{"title":"Elasticsearch"}} }如果用 match 下指定了一個確切值, 在遇到數字, 日期, 布爾值或者 not_analyzed 的字符串時, 它將為你搜索你給定的值,舉幾個例子
{ "match": { "age": 26 }}{ "match": { "date": "2014-09-01" }}{ "match": { "public": true }}{ "match": { "tag": "full_text" }}例子
做精確匹配搜索時最好用過濾語句, 因為過濾語句可以緩存數據。
multi_match 查詢
multi_match 查詢允許你做 match 查詢的基礎上同時搜索多個字段
{"multi_match": {"query": "full text search","fields": ["title","body"]} }POST http://localhost:9200/book/novel/_search
{"query":{"multi_match":{"query":"李四","fields":["author","title"]}} }bool 查詢
bool 查詢與 bool 過濾相似, 用于合并多個查詢子句。 不同的是, bool 過濾可以直接給出是否匹配成功, 而 bool 查詢要計算每一個查詢子句的 _score (相關性分值)
- must :: 查詢指定文檔一定要被包含。
- must_not :: 查詢指定文檔一定不要被包含。
- should :: 查詢指定文檔, 有則可以為文檔相關性加分
上述查詢將會找到 title 字段中包含 “how to make millions”, 并且 “tag” 字段沒有被標為 spam. 如果有標識為 "starred"或者發布日期為2014年之前, 那么這些匹配的文檔將比同類網站等級高.
如果 bool 查詢下沒有 must 子句, 那至少應該有一個 should 子句。 但是 如果有 must 子句, 那么沒有 should 子句也可以進行查詢。
Filter DSL
term 過濾
term 主要用于精確匹配哪些值, 比如數字, 日期, 布爾值或 not_analyzed 的字符串(未經分析的文本數據類型)
term僅允許指定一個匹配條件 ,即 value只能有一個值
舉例:過濾查詢"public_date" 精確匹配 "2017-08-15"的數據
{"query":{"term":{"public_date": "2017-08-15"}} }POST http://localhost:9200/book/novel/_search
terms 過濾
terms 允許指定多個匹配條件。 如果某個字段指定了多個值, 那么文檔需要一起去做匹配。
例子 查詢author匹配 "李三"或者"孫悟空"的數據
POST http://localhost:9200/book/novel/_search
{"query":{"terms":{"author":["李三","孫悟空"]}} }range 過濾
range 過濾 按照指定范圍查找一批數據
范圍操作符包含:
- gt 大于
- gte 大于等于
- lt 小于
- lte 小于等于
例子: 過濾查詢 字數 大于等于1000 小于2000的數據
POST http://localhost:9200/book/novel/_search
exists 和 missing 過濾
exists 和 missing 過濾可以用于查找文檔中是否包含指定字段或沒有某個字段, 類似于SQL語句中的 IS_NULL 條件。
這兩個過濾只是針對已經查出一批數據來, 但是想區分出某個字段是否存在的時候使用。
目前es不推薦使用missing過濾, 使用bool.must_not + exists來替代
"bool": {"must_not": {"exists": {"field": "title"}}}例子 查詢是否存在 名為 xxxx 的字段
POST http://localhost:9200/book/novel/_search
{"query":{"exists":{"field":"xxxx"}} }bool 過濾
bool 過濾可以用來合并多個過濾條件查詢結果的布爾邏輯,它包含一下操作符:
- must :: 多個查詢條件的完全匹配,相當于 and。
- must_not :: 多個查詢條件的相反匹配,相當于 not。
- should :: 至少有一個查詢條件匹配, 相當于 or。
這些參數可以分別繼承一個過濾條件或者一個過濾條件的數組:
例子
{"query": {"bool": {"must": {"term": {"folder": "inbox"}},"must_not": {"term": {"tag": "spam"}},"should": [{"term": {"starred": true}},{"term": {"unread": true}}]}} }查詢與過濾條件的合并
查詢語句和過濾語句可以放在各自的上下文中。 在 ElasticSearch API 中我們會看到許多帶有 query 或 filter 的語句。
這些語句既可以包含單條 query 語句, 也可以包含一條 filter 子句。
換句話說, 這些語句需要首先創建一個 query 或 filter 的上下文關系。
復合查詢語句可以加入其他查詢子句, 復合過濾語句也可以加入其他過濾子句。 通常情況下, 一條查詢語句需要過濾語句的輔助, 全文本搜索除外。
所以說, 查詢語句可以包含過濾子句, 反之亦然。 以便于我們切換 query 或 filter 的上下文。 這就要求我們在讀懂需求的同時構造正確有效的語句。
帶過濾的查詢語句
假設我們有這樣一條查詢語句:
{"match": {"email": "business opportunity"} }然后我們想要讓這條語句加入 term 過濾, 在收信箱中匹配郵件:
{"term": {"folder": "inbox"} }search API中只能包含 query 語句, 所以我們需要用 filtered 來同時包含 “query” 和 “filter” 子句 【過濾查詢已被棄用,并在ES 5.0中刪除,如下會在我們用的5.x版本中報錯】
{"filtered": {"query": {"match": {"email": "business opportunity"}},"filter": {"term": {"folder": "inbox"}}} }我們在外層再加入 query 的上下文關系:
{"query": {"filtered": {"query": {"match": {"email": "business opportunity"}},"filter": {"term": {"folder": "inbox"}}}} }報錯了。。。。 改成使用bool / must / filter查詢
{"query": {"bool": {"must": {"match": {"email": "business opportunity"}},"filter": {"term": {"folder": "inbox"}}}} }單條過濾語句
在 query 上下文中, 如果你只需要一條過濾語句, 比如在匹配全部郵件的時候, 你可以 省略 query 子句( 5.x以后的版本 需要用bool 代替 filtered):
{"query": {"bool": {"filter": {"term": {"folder": "inbox"}}}} }如果一條查詢語句沒有指定查詢范圍, 那么它默認使用 match_all 查詢 ,等同于
{"query": {"bool": {"must": {"match_all": {}},"filter": {"term": {"folder": "inbox"}}}} }上面說的是 查詢中使用過濾。 那過濾中使用查詢呢?
我們很少用到的過濾語句中包含查詢,為了語法的完整性,ES也支持這種。 只有在過濾中用到全文本匹配時候才會使用這種結構。
驗證查詢 (_validate)
查詢語句可以變得非常復雜, 特別是與不同的分析器和字段映射相結合后。
validate API 可以驗證一條查詢語句是否合法。
POST http://localhost:9200/book/novel/_validate/query
重點看 valid 的返回結果
查看錯誤信息
想知道語句非法的具體錯誤信息, 需要加上 explain 參數:
POST: http://localhost:9200/book/novel/_validate/query?explain
查看ES如何執行的
如果是合法語句的話, 使用 explain 參數可以返回一個帶有查詢語句的可閱讀描述, 可以幫助了解查詢語句在ES中是如何執行的
以 以下的JSON為例
{"query":{"match":{"title":"Elasticserach"}} }POST http://localhost:9200/book/novel/_validate/query?explain
關鍵請求: /_validate/query?explain
返回:
{"valid": true,"_shards": {"total": 1,"successful": 1,"failed": 0},"explanations": [{"index": "book","valid": true,"explanation": "+title:elasticserach #_type:novel"}] }explanation 會為每一個索引返回一段描述, 因為每個索引會有不同的映射關系和分析器. 上面的就只有一個。 ES如何查詢是和分詞器有關的。
總結
以上是生活随笔為你收集整理的Elasticsearch-05Elasticsearch之查询与过滤的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Elasticsearch-04 ES中
- 下一篇: Elasticsearch-06 Spr