Elasticsearch NEST:明确指定 Id 似乎会导致搜索分数不一致

Elasticsearch NEST: specifying Id explicitly seems to cause inconsistent search scores

我有一个模型 class 看起来像这样:

public class MySearchDocument
{
    public string ID { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }

    public int DBID { get; set; }
}

我们总是使用批量索引。默认情况下,我们的搜索会执行相对简单的 multi_match,并赋予 IDName 更大的权重,如下所示:

{
    "query": {
        "multi_match": {
            "query": "burger",
            "fields": [
                "ID^1.2",
                "Name^1.1",
                "Description"
            ],
            "auto_generate_synonyms_phrase_query": true
        }
    }
}

我以前只是依赖 Id inference,允许 Elasticsearch 使用我的 ID 属性 作为其 Id 用途,但由于一些原因,它变得更可取 DBID 作为 Elasticsearch 中的 Id 属性。我尝试了这 3 种不同的方式,分别 和组合 :

  1. 批量索引时显式:new BulkIndexOperation<MySearchDocument>(d) { Id = d.DBID }
  2. ConnectionSettings中使用DefaultMappingFor<MySearchDocument>(d => d.IdProperty(p => p.DBID))
  3. MySearchDocument 上使用属性:[ElasticsearchType(IdProperty = nameof(DBID))]

所有这些似乎都按预期工作;索引文档中的 _id 字段被设置为我的 DBID 属性。但是,在我的集成测试中,搜索结果完全出乎意料。具体来说,我有一个测试:

  1. 从头开始创建新索引。
  2. 用少量 MySearchDocuments
  3. 填充它
  4. 在索引上发出 Refresh 以确保它已准备就绪。
  5. 发出搜索。
  6. 断言结果按预期顺序返回。

通过 Id 推断,此测试始终通过。使用上述任何或所有技术切换 Id 字段时,它会通过 maybe 一半的时间。查看原始结果,总是会返回正确的文档,但是 _score 对于测试 运行 测试 运行 中的同一文档通常会有所不同。有时,不同的分数是与 ID 字段与搜索词匹配的文档相关联的分数,有时是另一个文档的分数。

我已经尝试将测试编码为 运行 重复并并行。我试过在 发出 Refresh 之后等待几秒钟 ,以确保索引已准备就绪。 None 其中有所不同 - 测试通过 Id 推理一致,并且始终不一致。我知道这个世界上没有什么是真正随机的,所以我觉得我一定在这里遗漏了什么。让我知道更多详细信息是否有帮助。提前致谢。

搜索相关性分数按分片计算,_id 值的哈希算法确定给定文档将被索引到哪个主分片。

听起来您可能会在索引 N > 1 主文档的小样本 时看到这种效果碎片;在这种情况下,本地相关性分数可能会有所不同,足以在返回的一些看起来很奇怪的 _score 中体现出来。有了更大的文档集和均匀分布,本地分片分数的差异就会减少。

出于测试目的,您可以采用多种方法来克服此问题:

  1. 使用单个主分片

  1. 使用dfs_query_then_fetch when making the search request. This tells Elasticsearch to take the local relevancy scores first in order to calculate global relevancy scores, then use global scores for _score. There is a slight overhead to using dfs_query_then_fetch.

另请参阅 Elasticsearch 权威指南中的 "Relevance is Broken!" 部分;尽管该指南提到了 Elasticsearch 2.x,但其中大部分内容与更高版本仍然非常相关。