前言
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的方式对查询的结果进行更精确地控制。
网友评论