我正在使用Elasticsearch 7.3进行产品搜索。产品标题的格式不同,但是对此我无能为力。
某些标题可能看起来像这样:
Ford Hub Bearing
和其他这样的人:
Hub bearing for a Chevrolet Z71 - model number 5528923-01
如果有人搜索“雪佛兰轮毂轴承”,则“福特轮毂轴承”产品排名#1,雪佛兰零件排名#2。如果我从产品标题中删除所有多余的文本(型号5528923-01),则雪佛兰部件将根据需要排名第一。
不幸的是,我无法修复产品标题,因此当有人搜索Chevrolet Hub Bearing
时,我需要将雪佛兰零件排名为#1。我只是将name
的类型设置为text
,并在索引中应用了standard
分析器。这是我的查询代码:
{
query:{
bool: {
must: [
{
multi_match:{
fields:
[
'name'
],
query: "Chevrolet Hub Bearing"
}
}
]
}
}
}
答案 0 :(得分:2)
Elasticsearch使用BM25算法在评分公式中使用字段长度。这就是为什么较长的文档即使匹配更多的术语也能排在第二位的原因。
我建议您阅读有关BM25的精彩博客文章: how-shards-affect-relevance-scoring-in-elasticsearch 和 the-bm25-algorithm-and-its-variables
但是您可以调整bm25算法来避免这种行为。这是用于Elasticsearch的{{3}}和bm25 documentation
基于TF / IDF的相似性,具有内置的tf规范化功能,并且 应该适用于短字段(例如名称)。参见Okapi_BM25 更多细节。这种相似性具有以下选项:
k1 =>控制非线性项频率归一化(饱和)。 默认值为1.2。
b =>控制文件长度 标准化tf值。默认值为0.75。
discount_overlaps => 确定是否重叠标记(位置增量为0的标记) 计算范数时将被忽略。默认情况下为true,这意味着 计算规范时,重叠标记不计算在内。
因此,您应该在索引设置中像这样配置新的相似性:
PUT <index>
{
"settings": {
"index": {
"number_of_shards": 1
},
"similarity": {
"my_bm25_without_length_normalization": {
"type": "BM25",
"b": 0
}
}
},
"mappings": {
"doc": {
"properties": {
"name": {
"type": "text",
"similarity": "my_bm25_without_length_normalization"
}
}
}
}
}
然后,if将停止惩罚得分较长的姓名。长度归一化将保留在其他字段中。
答案 1 :(得分:1)
我乍看之下只有2条建议:
1。在该字段上使用英语分析器。 我认为查询中词条之间的距离会影响文档的评分,而我错了(编辑:如@Pierre Mallet所指出的,在multi_query中不是这种情况),标准分析器会保留类似“ for”和“ a”,可能会降低文档的评分,因为“ for a”被分析器视为令牌。
2。如果您有描述或详细文档之类的内容,则可以将该字段添加到multi_match字段列表中,并使用^ 2调整字段的评分以进行数学评分(名称的相关性比相关性更重要描述的内容,但描述的内容在某些结果上可能是一个不错的决定因素),请参见以下示例:
isnull(emp.age, 'x') <> isnull(mst.age, 'x') -- fails
您还可以探索multi_match的类型参数,它会影响结果评分的行为。有关更多详细信息,请参见此documentation。