ES 20 - 查詢Elasticsearch中的資料 (基於DSL的查詢, 包括validate、match、bool)
目錄
- 1 什麼是DSL
- 2 _validate - 校驗查詢語句是否合法
- 3 match query - 匹配查詢
- 3.1 簡單功能示例
- 3.1.1 查詢所有文件
- 3.1.2 查詢滿足一定條件的文件
- 3.1.3 分頁查詢文件
- 3.1.4 指定返回的結果中包含的欄位
- 3.2 精確查詢 - match_phrase
- 3.2.1 精確匹配 - exact value
- 3.2.2 全文搜尋 - full text
- 3.3 控制匹配規則 - operator
- 3.4 指定命中的百分比 - minimum_should_match
- 3.5 多欄位的匹配 - multi_match
- 3.1 簡單功能示例
- 4 bool query - 布林查詢(真假查詢)
- 4.1 簡單功能示例
- 4.2 巢狀使用bool query
- 4.3 直接filter操作 - 使用constant_score
- 4.4 指定should的匹配個數 - minimum_should_match
1 什麼是DSL
DSL: Domain Specific Language, 領域特定語言, 指的是專注於某個應用程式領域的、具有高度針對性的計算機語言.
Query String 與 Query DSL之間的區別:
Query String: 在請求的URL後直接拼接查詢條件;
Query DSL: 在請求的Request Body中攜帶查詢條件.
DSL功能強大, 可以構建複雜的查詢、過濾、聚合條件, 所以這種查詢方式的用途最廣.
2 _validate - 校驗查詢語句是否合法
對於複雜的查詢, 很有必要在查詢前使用validate API
進行驗證, 保證DSL語句的正確有效:
// 要查詢name中包含"java"的文件:
GET shop/it_book/_validate/query?explain
{
"query": {
"math": { // 錯誤的查詢名稱, 應該是match
"name": "java"
}
}
}
// 校驗結果:
{
"valid": false,
"error": "org.elasticsearch.common.ParsingException: no [query] registered for [math]"
}
// 修改math為match後, 校驗結果為:
{
"valid": true,
"_shards": {
"total": 1,
"successful": 1,
"failed": 0
},
"explanations": [
{
"index": "shop",
"valid": true, // 校驗通過, DSL有效
"explanation": "+name:java #_type:it_book" // 查詢條件, +表示必須存在
}
]
}
3 match query - 匹配查詢
3.1 簡單功能示例
3.1.1 查詢所有文件
GET shop/it_book/_search
{
"query": {
"match_all": {}
}
}
3.1.2 查詢滿足一定條件的文件
查詢name中包含"java"的文件, 同時按照價格升序排序:
GET shop/it_book/_search
{
"query": {
"match": {
"name": "java"
}
},
"sort": [
{
"price": {"order": "asc"}
}
]
}
3.1.3 分頁查詢文件
GET shop/it_book/_search
{
"query": {
"match_all": {}
},
"from": 0, // 開始記錄數, 起始數為0
"size": 1 // 頁大小, 即每頁顯示的記錄數
}
3.1.4 指定返回的結果中包含的欄位
GET shop/it_book/_search
{
"query": {
"match_all": {}
},
"_source": [
"name", // 顯示商品名稱
"price" // 顯示商品價格
]
}
3.2 精確查詢 - match_phrase
不同的資料型別在建立倒排索引時, 有的會作為full text處理, 有的作為exact value處理.
對查詢串分詞時, 使用的分析器(analyzer)必須和建立index時使用的相同, 否則將檢索不到準確的資料.
3.2.1 精確匹配 - exact value
常見的exact value型別有date - 日期型別.
ES檢索時, 不會對String進行分詞, 而是完全根據String的值去精確匹配, 查詢相應的文件.
在DSL中, 通過match_phrase
短語匹配達到精確匹配的目的 —— 不會對查詢串進行分詞, 而是直接精確匹配查詢.
示例: 查詢name中包含"thinking in java"的文件, 不會對查詢串進行分詞:
GET shop/_search
{
"query": {
"match_phrase": {
"name": "thinking in java"
}
}
}
3.2.2 全文搜尋 - full text
常見的full text型別有: text - 文字串.
ES檢索時, 會對檢索串進行分詞, 包括縮寫、時態、同義詞等轉換手段, 然後根據分詞結果與倒排索引進行匹配, 查詢相應的文件.
索引中只要有任意一個相關field的分詞 匹配拆分後的詞, 這個文件就可以出現在結果中, 只是匹配度越高的排名越靠前.
示例: 查詢name中包含"thinking in java"的文件, 會將查詢串拆分為"think", "in", "java"三個詞:
GET shop/_search
{
"query": {
"match": {
"name": "thinking in java"
}
}
}
3.3 控制匹配規則 - operator
operator
操作符, 用來指定ES對分詞後的詞項如何進行檢索過濾. 選項有:
and, 作用 == match_phrase, 即全部匹配;
or, 作用 == match, 即部分匹配.
使用示例:
GET shop/_search
{
"query": {
"match": {
"name": { // 要查詢的field
"query": "程式設計思想",
"operator": "or" // 操作符
}
}
}
}
3.4 指定命中的百分比 - minimum_should_match
minimum_should_match
用來指定最少要匹配多少比例的分詞, 才算符合條件並返回結果.
示例: 搜尋name中包含"併發程式設計的藝術", 被拆分成"併發", "程式設計", "藝術"等詞, 現在要求至少匹配50%的分詞, 可以這樣:
GET shop/_search
{
"query": {
"match": {
"name": {
"query": "併發程式設計的藝術",
"minimum_should_match": "50%"
}
}
}
}
當然這種需求也可以用 must、must_not、should 匹配同一個欄位的方式進行組合查詢.
3.5 多欄位的匹配 - multi_match
multi_match
用來對多個欄位同時進行匹配: 任意一個欄位中存在相應的分詞, 就可作為結果返回.
示例 ① : 查詢 name 或 desc 欄位中包含 "面試經典" 的文件 —— 會對查詢串進行分詞:
GET shop/_search
{
"query": {
"multi_match": {
"query": "面試經典",
"fields": [
"name",
"desc"
]
}
}
}
示例 ② : 查詢 name 或 desc 欄位中同時包含 "面試經典" 的文件 —— 不對查詢串進行分詞:
GET shop/_search
{
"query": {
"multi_match": {
"query": "面試經典",
"type": "cross_fields", // 還有best_fields、most_fields、phrase、phrase_prefix選項
"operator": "and", // 全部匹配, or是部分匹配
"fields": [
"name",
"desc"
]
}
}
}
4 bool query - 布林查詢(真假查詢)
bool query, 顧名思義, 就是 真假/有無 查詢. 包括4個子查詢:
① must - 必須匹配, 類似於SQL中的
=
;
② must_not - 必須不匹配, 類似於SQL中的!=
;
③ should - 不強制匹配, 類似於SQL中的or
;
④ filter - 過濾, 將滿足一定條件的文件篩選出來.
除filter之外, 每個子查詢都會根據自己的條件計算出每個文件的相關度分數, 然後bool綜合所有分數, 合併為一個.
4.1 簡單功能示例
GET shop/_search
{
"query": {
"bool": {
"must":[
{ "match": { "name": "Java" } }
],
"must_not": [
{ "match": { "desc": "程式設計" } }
],
"should": [
{ "match": { "publisher": "機械工業" } }
],
"filter": {
"bool": {
"must": [
{ "range": { "date": { "gte": "2010-01-01" }}},
{ "range": { "price": { "lte": 99.00 }}}
]
}
}
}
}
}
4.2 巢狀使用bool query
GET shop/_search
{
"query": {
"bool": {
"should": [
{ "term": { "name.keyword": "Java程式設計思想" } },
{
"bool": {
"must": [
{ "term": { "product_desc": "刷頭" } }
]
}
}
]
}
}
}
4.3 直接filter操作 - 使用constant_score
如果不指定query條件而直接filter, 將丟擲
no [query] registered for [filter]
, 此時通過constant_score
即可實現直接filter.
GET shop/_search
{
"query": {
"constant_score": {
"filter": {
"range": { "price": { "gte": 80 } }
}
}
}
}
4.4 指定should的匹配個數 - minimum_should_match
如果組合查詢中沒有must
, 就會至少匹配一個should
.
可以通過 minimum_should_match
指定匹配的should
的個數.
GET shop/_search
{
"query": {
"bool": {
"should": [
{ "match": { "name": "java" } },
{ "match": { "desc": "程式設計"} },
{ "match": { "price": 109 } }
],
"minimum_should_match": 2
}
}
}
參考資料
Elasticsearch DSL 常用語法介紹
版權宣告
作者: 馬瘦風(https://healchow.com)
出處: 部落格園 馬瘦風的部落格(https://www.cnblogs.com/shoufeng)
感謝閱讀, 如果文章有幫助或啟發到你, 點個[好文要頂