前言
有时我们在搜索电影的时候,包含了多个条件,比如主演是周星驰,打分8分以上,上映时间是1990年~2001年的,那么Elasticsearch又该如何帮我们做查询呢?这里我们可以用 bool 查询来实现需求。这种查询将多查询组合在一起,成为用户自己想要的 bool 查询。
bool 查询
一个 bool 查询,可以包含一个或多个查询语句进行组合。
有4种参数
- must:文档必须匹配这些条件才能被包含进来。贡献算分。
- should:文档选择性匹配,如果满足这些语句中的任意语句,将增加 _score ,否则,无任何影响。贡献算分。
- must_not:文档必须不匹配这些条件才能被包含进来。
- filter:必须 匹配,但它以不评分、过滤模式来进行。这些语句对评分没有贡献,只是根据过滤标准来排除或包含文档。不贡献算分。
基本语法
- bool 里面的子查询继续嵌套 bool 查询
- 子查询可以以任意顺序出现
- 如果没有 must 语句,那么至少需要能够匹配其中的一条 should 语句。但如果存在至少一条 must 语句,则对 should 语句的匹配没有要求。
- must等可以跟一个对象(“{}”),也可以跟数组(“[]”)
{
"bool": {
"must": { "match": { "title": "how to make millions" }},
"must_not": { "match": { "tag": "spam" }},
"should": [
{ "match": { "tag": "starred" }}
],
"filter": {
"bool": {
"must": [
{ "range": { "date": { "gte": "2014-01-01" }}},
{ "range": { "price": { "lte": 29.99 }}}
],
"must_not": [
{ "term": { "category": "ebooks" }}
]
}
}
}
}
一个航班查询的例子,搜索去往美国的,当地天气是晴朗的,不从日本出发的,票价小于等于1000的航班。
GET kibana_sample_data_flights/_search
{
"size": 5,
"query": {
"bool": {
"must": [
{
"term": {
"DestCountry": "US"
}
},
{
"term": {
"DestWeather": "Sunny"
}
}
],
"must_not": {
"term": {
"OriginCountry": "JP"
}
},
"filter": {
"range": {
"AvgTicketPrice": {
"lte": 1000
}
}
}
}
}
}
控制相关性
那么多个字段的查询,我们该如何影响其相关性的算分呢?
层级嵌套
同一层级下的字段是竞争关系,具有相同权重,可以通过嵌套改变对算分的影响。
GET animals/_search
{
"query": {
"bool": {
"should": [
{"term": {"text": "brown"}},
{"term": {"text": "red"}},
{"term": {"text": "quick"}},
{"term": {"text": "dog"}}
]
}
}
}
GET animals/_search
{
"query": {
"bool": {
"should": [
{"term": {"text": "brown"}},
{"term": {"text": "red"}},
{"bool": {
"should": [
{"term": {"text": "quick"}},
{"term": {"text": "dog"}}
]
}
}
]
}
}
}
boosting
控制字段的权重,可以使用boosting,默认值是1,可正可负。
- 当boost>1时,打分的相关性相对提升
- 当0<boost<1时,打分的相关性相对降低
- 当boost<0时,贡献负分
精简语法,可以在match里面指定boost,比如上面的航班信息DestCountry部分字段设置权重。
GET kibana_sample_data_flights/_search
{
"explain": true,
"size": 5,
"query": {
"bool": {
"must": [
{
"match": {
"DestCountry": {
"query": "US",
"boost": 10
}
}
},
{
"term": {
"DestWeather": "Sunny"
}
}
],
"must_not": {
"term": {
"OriginCountry": "JP"
}
},
"filter": {
"range": {
"AvgTicketPrice": {
"lte": 1000
}
}
}
}
}
}
完整boosting语法,positive正向作用,negative负向作用,negative_boost负向作用的权重,可以用来降级匹配的文档,不像“NOT”逻辑运算直接去除相关的文档
GET movies/_search
{
//"explain": true,
"query": {
"boosting": {
"positive": {
"term": {
"title": {
"value": "beautiful"
}
}
},
"negative": {
"term": {
"title": {
"value": "mind"
}
}
},
"negative_boost": 0.2
}
}
}
constant_score 查询
尽管没有 bool 查询使用这么频繁,constant_score 查询也是我们工具箱里有用的查询工具。它将一个不变的常量评分应用于所有匹配的文档。它被经常用于你只需要执行一个 filter 而没有其它查询(例如,评分查询)的情况下。
GET movies/_search
{
"query": {
"constant_score": {
"filter": {
"term": {
"title": "beautiful"
}
}
}
}
}
参考资料
- https://www.elastic.co/guide/cn/elasticsearch/guide/current/combining-queries-together.html
- Elasticsearch核心技术与实战(阮一鸣--极客时间)