我有一个如下所示的模型类:
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
ID
给予更多权重和Name
,像这样:
{
"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 种不同的方式,单独和组合:
- 批量索引时明确:
new BulkIndexOperation<MySearchDocument>(d) { Id = d.DBID }
- 在
ConnectionSettings
使用DefaultMappingFor<MySearchDocument>(d => d.IdProperty(p => p.DBID))
- 在
MySearchDocument
上使用属性:[ElasticsearchType(IdProperty = nameof(DBID))]
所有这些似乎都按预期工作; _id
索引文档中的字段被设置为我的 DBID
属性(property)。然而,在我的集成测试中,搜索结果完全出乎预期。具体来说,我有一个测试:
- 从头开始创建新索引。
- 用少量
MySearchDocument
填充它s - 问题
Refresh
索引只是为了确保它已准备就绪。 - 发出搜索。
- 断言结果按预期顺序返回。
通过 Id 推断,该测试始终能够通过。当使用上述任何或所有技术切换 Id 字段时,它可能会通过一半的时间。查看原始结果,总是返回正确的文档,但是 _score
同一文档在不同的测试运行中通常会有所不同。有时,不同的分数是与 ID
的文档相关的分数。字段与搜索词匹配,其他时候它是不同文档的分数。
我尝试编写测试代码以重复并行运行。我尝试在发出 Refresh
后等待几秒钟,只是为了确保索引已准备好。这些都没有什么区别 - 测试通过与 Id 推断一致,并且始终与 Id 推断不一致。我知道这个世界上没有什么是真正随机的,所以我觉得我一定错过了一些东西。请告诉我更多详细信息是否有帮助。提前致谢。
最佳答案
搜索相关性分数是按分片计算的,并且基于 _id
值的哈希算法确定给定文档将被索引到哪个主分片。
听起来就像您在跨 N > 1
个主分片索引小样本文档时可能会看到这种效果;在这种情况下,本地相关性分数可能会有所不同,足以体现在返回的一些看起来很奇怪的 _score
中。随着文档集的增多和分布的均匀,本地分片分数的差异就会减小。
出于测试目的,您可以采取多种方法来克服此问题:
- 使用单个主分片
或
- 使用
dfs_query_then_fetch
当提出搜索请求时。这告诉 Elasticsearch 首先采用本地相关性分数来计算全局相关性分数,然后使用全局分数作为_score
。 There is a slight overhead to usingdfs_query_then_fetch
.
另请查看 "Relevance is Broken!" 部分来自 Elasticsearch 权威指南;尽管该指南引用了 Elasticsearch 2.x,但其中大部分内容仍然与后续版本非常相关。
关于Elasticsearch 巢 : specifying Id explicitly seems to cause inconsistent search scores,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53676107/