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
,并赋予 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
属性。但是,在我的集成测试中,搜索结果完全出乎意料。具体来说,我有一个测试:
- 从头开始创建新索引。
- 用少量
MySearchDocument
s 填充它
- 在索引上发出
Refresh
以确保它已准备就绪。
- 发出搜索。
- 断言结果按预期顺序返回。
通过 Id 推断,此测试始终通过。使用上述任何或所有技术切换 Id 字段时,它会通过 maybe 一半的时间。查看原始结果,总是会返回正确的文档,但是 _score
对于测试 运行 测试 运行 中的同一文档通常会有所不同。有时,不同的分数是与 ID
字段与搜索词匹配的文档相关联的分数,有时是另一个文档的分数。
我已经尝试将测试编码为 运行 重复并并行。我试过在 发出 Refresh
之后等待几秒钟 ,以确保索引已准备就绪。 None 其中有所不同 - 测试通过 Id 推理一致,并且始终不一致。我知道这个世界上没有什么是真正随机的,所以我觉得我一定在这里遗漏了什么。让我知道更多详细信息是否有帮助。提前致谢。
搜索相关性分数按分片计算,_id
值的哈希算法确定给定文档将被索引到哪个主分片。
听起来您可能会在索引 N > 1
主文档的小样本 时看到这种效果碎片;在这种情况下,本地相关性分数可能会有所不同,足以在返回的一些看起来很奇怪的 _score
中体现出来。有了更大的文档集和均匀分布,本地分片分数的差异就会减少。
出于测试目的,您可以采用多种方法来克服此问题:
- 使用单个主分片
或
- 使用
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,但其中大部分内容与更高版本仍然非常相关。
我有一个模型 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
,并赋予 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
属性。但是,在我的集成测试中,搜索结果完全出乎意料。具体来说,我有一个测试:
- 从头开始创建新索引。
- 用少量
MySearchDocument
s 填充它
- 在索引上发出
Refresh
以确保它已准备就绪。 - 发出搜索。
- 断言结果按预期顺序返回。
通过 Id 推断,此测试始终通过。使用上述任何或所有技术切换 Id 字段时,它会通过 maybe 一半的时间。查看原始结果,总是会返回正确的文档,但是 _score
对于测试 运行 测试 运行 中的同一文档通常会有所不同。有时,不同的分数是与 ID
字段与搜索词匹配的文档相关联的分数,有时是另一个文档的分数。
我已经尝试将测试编码为 运行 重复并并行。我试过在 发出 Refresh
之后等待几秒钟 ,以确保索引已准备就绪。 None 其中有所不同 - 测试通过 Id 推理一致,并且始终不一致。我知道这个世界上没有什么是真正随机的,所以我觉得我一定在这里遗漏了什么。让我知道更多详细信息是否有帮助。提前致谢。
搜索相关性分数按分片计算,_id
值的哈希算法确定给定文档将被索引到哪个主分片。
听起来您可能会在索引 N > 1
主文档的小样本 时看到这种效果碎片;在这种情况下,本地相关性分数可能会有所不同,足以在返回的一些看起来很奇怪的 _score
中体现出来。有了更大的文档集和均匀分布,本地分片分数的差异就会减少。
出于测试目的,您可以采用多种方法来克服此问题:
- 使用单个主分片
或
- 使用
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 usingdfs_query_then_fetch
.
另请参阅 Elasticsearch 权威指南中的 "Relevance is Broken!" 部分;尽管该指南提到了 Elasticsearch 2.x,但其中大部分内容与更高版本仍然非常相关。