前言
Elasticsearch有Query和Filter兩種不同的Context。
- Query Context,會進行相關性算分
- Filter Context,不會進行相關性算分,這種方式可利用緩存來提高檢索的速度和性能。
Bool查詢
Bool查詢是一種復合查詢,是一個或多個查詢子句的組合。Bool查詢總共包含4種子句。其中,兩種會影響算分,另外兩種不影響算分。
子句 | 類型 | 影響結果 |
---|---|---|
must | Query Context | 必須匹配。貢獻算分 |
shoud | Query Context | 選擇性匹配,至少滿足一條。貢獻算分 |
must_not | Filter Context | 過濾子句,必須不能匹配,但不貢獻算分 |
filter | Filter Context | 過濾子句,必須匹配,但不貢獻算分 |
Bool查詢語法有以下特點
- 子查詢可以任意順序出現
- 可以嵌套多個查詢,包括bool查詢
- 如果bool查詢中沒有must條件,should中必須至少滿足一條才會返回結果。
POST /products/_bulk
{ "index": { "_id": 1 }}
{ "price" : 10,"avaliable":true,"date":"2018-01-01", "productID" : "XHDK-A-1293-#fJ3" }
{ "index": { "_id": 2 }}
{ "price" : 20,"avaliable":true,"date":"2019-01-01", "productID" : "KDKE-B-9947-#kL5" }
{ "index": { "_id": 3 }}
{ "price" : 30,"avaliable":true, "productID" : "JODL-X-1937-#pV7" }
{ "index": { "_id": 4 }}
{ "price" : 30,"avaliable":false, "productID" : "QQPX-R-3956-#aD8" }
# 基本語法
POST /products/_search
{
"query": {
"bool" : {
"must" : {
"term" : { "price" : "30" }
},
"filter": {
"term" : { "avaliable" : "true" }
},
"must_not" : {
"range" : {
"price" : { "lte" : 10 }
}
},
"should" : [
{ "term" : { "productID.keyword" : "JODL-X-1937-#pV7" } },
{ "term" : { "productID.keyword" : "XHDK-A-1293-#fJ3" } }
],
"minimum_should_match" :1
}
}
}
數組的精確匹配
在前面章節,我們在查詢數組的時候遇到了一個問題,即:默認的查詢行為是包含就返回,而不是相等。那么,有沒有一種方式可以實現相等
的這種場景呢?
答案是:有的。解決思路就是增加一個count字段用于標識數組內元素的個數,然后通過Bool查詢來實現。
# 改變數據模型,增加字段。解決數組包含而不是精確匹配的問題
POST /newmovies/_bulk
{ "index": { "_id": 1 }}
{ "title" : "Father of the Bridge Part II","year":1995, "genre":"Comedy","genre_count":1 }
{ "index": { "_id": 2 }}
{ "title" : "Dave","year":1993,"genre":["Comedy","Romance"],"genre_count":2 }
# Query。must,有算分
POST /newmovies/_search
{
"query": {
"bool": {
"must": [
{"term": {"genre.keyword": {"value": "Comedy"}}},
{"term": {"genre_count": {"value": 1}}}
]
}
}
}
# Filter。不參與算分,結果的score是0
POST /newmovies/_search
{
"query": {
"bool": {
"filter": [
{"term": {"genre.keyword": {"value": "Comedy"}}},
{"term": {"genre_count": {"value": 1}}}
]
}
}
}
特別注意:Filter的兩種方式,返回的
_score
都是0,而Query的兩種卻不是0。
Bool嵌套查詢
# 嵌套,實現了 should not 邏輯
POST /products/_search
{
"query": {
"bool": {
"must": {
"term": {
"price": "30"
}
},
"should": [
{
"bool": {
"must_not": {
"term": {
"avaliable": "false"
}
}
}
}
],
"minimum_should_match": 1
}
}
}
查詢語句結構的影響
查詢語句的結構,也會對相關度算分產生影響。
- 同一層級下的競爭字段,具有相同的權重
- 通過嵌套bool查詢,可以改變對算分的影響
POST /animals/_search
{
"query": {
"bool": {
"should": [
{ "term": { "text": "brown" }},
{ "term": { "text": "red" }},
{ "term": { "text": "quick" }},
{ "term": { "text": "dog" }}
]
}
}
}
POST /animals/_search
{
"query": {
"bool": {
"should": [
{ "term": { "text": "quick" }},
{ "term": { "text": "dog" }},
{
"bool":{
"should":[
{ "term": { "text": "brown" }},
{ "term": { "text": "brown" }},
]
}
}
]
}
}
}
Boosting
# 刪除并創建索引
DELETE news
POST /news/_bulk
{ "index": { "_id": 1 }}
{ "content":"Apple Mac" }
{ "index": { "_id": 2 }}
{ "content":"Apple iPad" }
{ "index": { "_id": 3 }}
{ "content":"Apple employee like Apple Pie and Apple Juice" }
# 默認的查詢,3的記錄排在第一
POST news/_search
{
"query": {
"bool": {
"must": {
"match":{"content":"apple"}
}
}
}
}
# must_not的方式,將3的記錄強制排除掉
POST news/_search
{
"query": {
"bool": {
"must": {
"match":{"content":"apple"}
},
"must_not": {
"match":{"content":"pie"}
}
}
}
}
# 通過Boosting的方式,將3的記錄也納入結果集,只是排名會靠后。
# positive表示正向激勵
# negative表示負向激勵,negative_boost表示激勵的比重
POST news/_search
{
"query": {
"boosting": {
"positive": {
"match": {
"content": "apple"
}
},
"negative": {
"match": {
"content": "pie"
}
},
"negative_boost": 0.5
}
}
}
總結
- 我們簡單地討論了
query context
和filter context
,了解了他們的差異。 - 我們還學習了bool查詢,它可以包含多個子句。
- 查詢結構的調整會對相關性算分產生影響。
- 我們再次通過一個例子學習了boosting,可使用Boosting和Boosting Query的方式對查詢的結果進行更精確地控制。