我们刚刚升级到Elasticsearch 2.3.1(从1.7),我们得到了奇怪的搜索行为,我无法解释。似乎发生的是,包含bool
查询和sort
子句的搜索请求返回:
- 似乎与给定的搜索条件不匹配的文档。
- 每次请求对匹配文档
total
的估计差异很大
请求行为的最小示例:
post pim_search_1/_search
{
"explain": false,
"track_scores": false,
"sort": [
{
"product_id": {
"order": "desc"
}
}
],
"query": {
"bool": {
"filter": [
{
"terms": {
"publication": [
"public"
]
}
},
{
"query_string": {
"query": "iphone",
"default_operator": "and"
}
}
]
}
}
}
在这个例子中,"iphone"的查询字符串根本没有返回iphone。将explain
设置为true对于根本没有匹配项的文档产生如下结果:
"_explanation": {
"value": 0,
"description": "Failure to meet condition(s) of required/prohibited clause(s)",
"details": [
{
"value": 0,
"description": "no match on required clause (#ConstantScore(publication:public) #_all:iphone)",
所以文档没有匹配子句,但它仍然返回?
我们找到了两种解决方法:
- 对
_score
进行排序或完全省略sort
子句。在其他任何地方排序,比如上面的字段或_doc
,都会产生不稳定的行为。 - 包含
track_scores : true
请求
所以它似乎与得分和相关性有关。但由于我们在自己的领域进行排序,我们对相关性或分数不感兴趣。如果没有变通方法,响应的max_score
是null
,每个文档的_score
也是如此。
这种行为是否可以用任何方式解释,或者我们是否应该查看集群运行状况/配置/损坏?根据集群,它的运行状况是绿色的,并且该索引的所有分片看起来都是健康的。它目前是一个小索引,在3个节点上有3个分片(每个分片1个副本)。
<标题> 更新我已经进一步调查了这个问题,它似乎与缓存有关。具体来说,_all
字段的字段数据缓存(我不是很熟悉Elasticsearch的内部,所以请纠正我,如果这不是一件事)。
复制
的步骤我有一个重现问题的数据集,留下评论,我可以发送给你。
使用以下查询:
post pim_search_1/_search
{
"fields": [
"_all"
],
"explain": true,
"size": 100,
"sort": [
{
"product_id": {
"order": "desc"
}
}
],
"query": {
"bool": {
"must": [
{
"query_string": {
"default_field": "_all",
"query": "surface",
"default_operator": "and"
}
}
],
"filter": [
{
"terms": {
"publication": [
"public"
]
}
}
]
}
}
}
- 执行查询。您在这里的查询字符串中搜索"surface",这应该会导致总共22个命中。这是正确的。执行这个查询多次(这似乎对步骤2很重要)。
- 将查询字符串更改为"iphone"。这仍然会导致22次命中,即使数据集只包含一个应该匹配的项。
_explanation
还提到,找到的文档实际上并不匹配,就像我上面的例子一样。 执行 - 再次执行"iphone"的查询。它现在应该只返回1次命中,这是正确的。也要多次执行这个。
- 再次执行查询"surface",这将只返回1次命中,并且
_explanation
再次声明它没有在结果文档上得到匹配。 - 从查询中删除
sort
子句,一切看起来正常。包含"track_scores" : true
也是如此。
post pim_search_1/_cache/clear
代替_cache/clear
,它也可以重新启动集群。
我说它与_all
字段有关,因为将query_string
的default_field
更改为primitive_name
字段(分析字段)会导致正确的行为。对于这个例子,我把_all
作为一个存储字段(它通常不与我们在一起),它在搜索结果中返回,所以你可以检查它(似乎不包含任何奇怪的东西)。
以上是在Elasticsearch 2.3.5的单节点集群(我的本地PC)上完成的。
这个Github问题似乎与我的问题相同,但当时无法复制并被关闭。
标题>这在Elasticsearch 2.4中已经修复:
https://github.com/elastic/elasticsearch/pull/20196