一 序
本文属于极客时间Elasticsearch核心技术与实战学习笔记系列。
二 Query Context & Filter Context
高级搜索的功能,支持多想文本输入,针对多个字段进行搜索
搜索引擎一般也提供时间,价格等条件过滤
在 ES 中,有 Query 和 Filter 两种 Context
Query Context :相关性算分
Filter Context :不需要算分(YES OR NO), 可以利用 Cache 获得更好的性能
条件组合
假设搜索一本电影
- 评论中包含了 Guitar ,用户打分高于 3 分,同时上映时间在 1993 到 2000 年之间
这个搜索包含了 3 段逻辑,针对不同的字段
- 评论字段中要包含 Guitar 、用户评论大于 3、上映时间日期在给定范围内
同时包含这三个逻辑,并且有比较好的性能
- 复合查询: bool Query
bool 查询
一个 bool 查询,是一个或者多个查询子句的组合
- 总共包含 4 种子句,其中 2 种会影响算分,2 种不影响算分
相关性并不只是全文本搜索的专利。也适合 yes | no 的子句,匹配的子句越多,相关性评分越高。如果多条查询子句被合并为一条复合查询语句,比如 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" }
这是一个bool搜索的例子,条件:价格是30.filter对算分无影响,对应的条件是true.must_not 对算分无影响。should的条件id满足两个之一。
如何解决结构化查询 -“包含而不是相等” 的问题
增加 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 }
#must,有算分
POST /newmovies/_search
{
"query": {
"bool": {
"must": [
{"term": {"genre.keyword": {"value": "Comedy"}}},
{"term": {"genre_count": {"value": 1}}}
]
}
}
}
must 有算分
Filter。不参与算分,结果的score是0
should 影响算分:对比前面可见这个分数高了。
bool 嵌套
#嵌套,实现了 should not 逻辑
POST /products/_search
{
"query": {
"bool": {
"must": {
"term": {
"price": "30"
}
},
"should": [
{
"bool": {
"must_not": {
"term": {
"avaliable": "false"
}
}
}
}
],
"minimum_should_match": 1
}
}
}
查询语句的结构,会对相关度算分产生影响
- 同一层级下的竞争字段,具有相同的权重
- 通过嵌套 bool 查询,可以改变对算分的影响
上面例子,左侧相同的权重,对比下右侧的,我们吧颜色该写到子查询,会影响到算分。
控制字段的 Boosting
demo:
DELETE blogs
POST /blogs/_bulk
{ "index": { "_id": 1 }}
{"title":"Apple iPad", "content":"Apple iPad,Apple iPad" }
{ "index": { "_id": 2 }}
{"title":"Apple iPad,Apple iPad", "content":"Apple iPad" }
1 先调整title的boost,返回对应2再前面
如果调整body的boost: 文档1会在前面
demo2:搜索新闻的例子
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条数据,要求搜索苹果公司的产品优先。
默认条件的搜索,不是符合预期。
加入must_not做过滤。返回2条。
通过调整boost,返回顺序也做了调整。
小结
- Query Context vs Filter Context
- Bool Query - 更多的条件组合
- 查询结构与相关性算分
- 如何控制查询的精确度
- Boosting & Boosting Query