1. Query 和 filter Context
相关阅读:https://www.elastic.co/guide/en/elasticsearch/reference/7.4/query-filter-context.html
在 ElasticSearch 中,有 Query 和 Filter 两种不同的 Context,其中 Query Context 会进行相关性算分,而 Filter Context 则不需要进行算分,其可以利用 Cache 一次获得更好的性能。
例如在 bool query 中的 must_not 和 filter 即为 Filter Context,而一般的查询都会进行相关性算分,即为 Query Context ,其会计算出 _score 的值。
例如 Filter Context 不影响相关性得分,其检索出来的 _score 值为 0,而 Query Context 检索出来的 _score 的值为实际计算出来的值:
2. Bool Query
相关阅读:https://www.elastic.co/guide/en/elasticsearch/reference/7.4/query-dsl-bool-query.html
假设现在要搜索一本电影,需要包含以下一些条件:
- 评论中包含了 Guitar,用户打分高于 3 分,同时上映日期要在 1993 与 2000 年之间
要实现这样的查询可以采用 bool query 进行实现。一个 bool query,是一个或者多个查询子句的组合,其总共包括 4 种子句,其中两种会影响算分,两种不影响算分。
相关性不只是全文本检索的专利,也适用于 yes or no 的子句,匹配的子句越多,相关性评分越高。如果多条查询子句被合并为一条复合查询语句,比如 bool query,则每个查询子句计算得出的评分会被合并到总的相关性评分中。
假设现在要查询 price 为 30,且同时不能小于等于 10 和 productID 需要是 JODL-X-1937-#pV7
或者 XHDK-A-1293-#fJ3
的有效产品,其 DSL 如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| 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 } } }
|
需要额外说明的是 minimum_should_match 参数用于设置返回的文档必须匹配的最少 should 分支数。不设置时则默认值为 0,在存在 must 子句时则不强制匹配 should 中的查询条件。
子查询可以任意顺序出现在 bool query 语句中,同时可以嵌套多个 bool query。同 should 一样,must、filter 和 must_not 都可以是数组格式以此来组合更多的查询条件。例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| POST /products/_search { "query": { "bool" : { "must" : [ { "bool": { "must": [ {"term" : { "price" : 30 }} ] } }, { "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 } } }
|
3. Boosting Query
相关阅读:https://www.elastic.co/guide/en/elasticsearch/reference/7.4/query-dsl-boosting-query.html
boosting 是控制相关度的一种手段,可以通过参数 boost 进行设置。当 boost 大于 1 时,打分的相关度相对性提升,大于 0 且小于 1 时,打分的权重会相对性降低,而小于 0 时则会贡献负分。
比如现在需要将 news 索引中内容包含 apple
的相关性得分更高,而包含 pie
的相关性得分打低,可以通过如下语句查询:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
| POST news/_search { "query": { "boosting": { "positive": { "match": { "content": "apple" } }, "negative": { "match": { "content": "pie" } }, "negative_boost": 0.5 // 负相关匹配条件 boost 权重设置偏低,相关性会降低 } } } // 响应 { "took" : 0, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 3, "relation" : "eq" }, "max_score" : 0.16786805, "hits" : [ { "_index" : "news", "_type" : "_doc", "_id" : "1", "_score" : 0.16786805, "_source" : { "content" : "Apple Mac" } }, { "_index" : "news", "_type" : "_doc", "_id" : "2", "_score" : 0.16786805, "_source" : { "content" : "Apple iPad" } }, { "_index" : "news", "_type" : "_doc", "_id" : "3", "_score" : 0.08640266, "_source" : { "content" : "Apple employee like Apple Pie and Apple Juice" } } ] } }
|
可以观察到 content 中包含 pie 的记录得分更低,更加靠后显示。