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