Elasticsearch 排名 shorter/less 相关标题第一
Elasticsearch ranking shorter/less relevant titles first
我正在使用 Elasticsearch 7.3 进行产品搜索。产品标题的格式不同,但我对此无能为力。
有些标题可能是这样的:
Ford Hub Bearing
还有这样的其他人:
Hub bearing for a Chevrolet Z71 - model number 5528923-01
如果有人搜索 "Chevrolet Hub Bearing","Ford Hub Bearing" 产品排名第一,雪佛兰零件排名第二。如果我从产品标题中删除所有额外的文本(型号 5528923-01),雪佛兰部件将根据需要排名第一。
不幸的是,我无法修复产品标题,因此当有人搜索时,我需要能够将雪佛兰部件排名为第一 Chevrolet Hub Bearing
。我只是将 name
的类型设置为 text
并在我的索引中应用了 standard
分析器。这是我的查询代码:
{
query:{
bool: {
must: [
{
multi_match:{
fields:
[
'name'
],
query: "Chevrolet Hub Bearing"
}
}
]
}
}
}
乍一看我只有2条建议:
1.use 该领域的英语分析器。 我认为查询中术语之间的距离会影响文档的评分,我错了(编辑:正如@Pierre Mallet 所指出的,multi_query 并非如此)标准分析器保留 "for" 和 "a" 之类的词,这可能会降低文档的分数,因为 "for a" 被分析器视为标记。
2.if 你有描述或详细文档之类的东西,你可以将该字段添加到你的 multi_match 字段列表并使用 ^2 调整字段的评分以在数学上操纵评分(相关性名称的相关性比描述的相关性更重要,但描述的内容可能是某些结果的一个很好的决胜局)参见以下示例:
"multi_match": {
"query": "open source",
"fields": [
"title^2",
"content"
]
}
您还可以探索 multi_match 的类型参数,它会影响结果评分的行为方式。有关更多详细信息,请参阅此 documentation。
Elasticsearch 在 BM25 算法的评分公式中使用字段长度。这就是为什么较长的文档即使匹配更多术语也会排在第二位的原因。
我建议您阅读那些关于 BM25 的精彩博文:
how-shards-affect-relevance-scoring-in-elasticsearch
和
the-bm25-algorithm-and-its-variables
但是您可以调整 bm25 算法来避免这种行为。这是 bm25 documentation for elasticsearch and here a post explaining how to do it
TF/IDF based similarity that has built-in tf normalization and is
supposed to work better for short fields (like names). See Okapi_BM25
for more details. This similarity has the following options:
k1 => Controls non-linear term frequency normalization (saturation).
The default value is 1.2.
b => Controls to what degree document length
normalizes tf values. The default value is 0.75.
discount_overlaps =>
Determines whether overlap tokens (Tokens with 0 position increment)
are ignored when computing norm. By default this is true, meaning
overlap tokens do not count when computing norms.
所以你应该像这样在你的索引设置中配置一个新的相似性:
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"
}
}
}
}
}
然后如果将停止惩罚更长的名字的得分。长度归一化将保留用于其他字段。
我建议将 multi_match
的 operator
parameter 设置为 and
:
{
"query": {
"bool": {
"must": [
{
"multi_match": {
"fields": ["name"],
"query": "Chevrolet Hub Bearing",
"operator": "and"
}
}
]
}
}
}
and
运算符可确保搜索短语中的所有单词都必须出现在生成的文档中。仅此设置就可以为您提供所需的结果。
我正在使用 Elasticsearch 7.3 进行产品搜索。产品标题的格式不同,但我对此无能为力。
有些标题可能是这样的:
Ford Hub Bearing
还有这样的其他人:
Hub bearing for a Chevrolet Z71 - model number 5528923-01
如果有人搜索 "Chevrolet Hub Bearing","Ford Hub Bearing" 产品排名第一,雪佛兰零件排名第二。如果我从产品标题中删除所有额外的文本(型号 5528923-01),雪佛兰部件将根据需要排名第一。
不幸的是,我无法修复产品标题,因此当有人搜索时,我需要能够将雪佛兰部件排名为第一 Chevrolet Hub Bearing
。我只是将 name
的类型设置为 text
并在我的索引中应用了 standard
分析器。这是我的查询代码:
{
query:{
bool: {
must: [
{
multi_match:{
fields:
[
'name'
],
query: "Chevrolet Hub Bearing"
}
}
]
}
}
}
乍一看我只有2条建议:
1.use 该领域的英语分析器。 我认为查询中术语之间的距离会影响文档的评分,我错了(编辑:正如@Pierre Mallet 所指出的,multi_query 并非如此)标准分析器保留 "for" 和 "a" 之类的词,这可能会降低文档的分数,因为 "for a" 被分析器视为标记。
2.if 你有描述或详细文档之类的东西,你可以将该字段添加到你的 multi_match 字段列表并使用 ^2 调整字段的评分以在数学上操纵评分(相关性名称的相关性比描述的相关性更重要,但描述的内容可能是某些结果的一个很好的决胜局)参见以下示例:
"multi_match": {
"query": "open source",
"fields": [
"title^2",
"content"
]
}
您还可以探索 multi_match 的类型参数,它会影响结果评分的行为方式。有关更多详细信息,请参阅此 documentation。
Elasticsearch 在 BM25 算法的评分公式中使用字段长度。这就是为什么较长的文档即使匹配更多术语也会排在第二位的原因。
我建议您阅读那些关于 BM25 的精彩博文: how-shards-affect-relevance-scoring-in-elasticsearch 和 the-bm25-algorithm-and-its-variables
但是您可以调整 bm25 算法来避免这种行为。这是 bm25 documentation for elasticsearch and here a post explaining how to do it
TF/IDF based similarity that has built-in tf normalization and is supposed to work better for short fields (like names). See Okapi_BM25 for more details. This similarity has the following options:
k1 => Controls non-linear term frequency normalization (saturation). The default value is 1.2.
b => Controls to what degree document length normalizes tf values. The default value is 0.75.
discount_overlaps => Determines whether overlap tokens (Tokens with 0 position increment) are ignored when computing norm. By default this is true, meaning overlap tokens do not count when computing norms.
所以你应该像这样在你的索引设置中配置一个新的相似性:
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"
}
}
}
}
}
然后如果将停止惩罚更长的名字的得分。长度归一化将保留用于其他字段。
我建议将 multi_match
的 operator
parameter 设置为 and
:
{
"query": {
"bool": {
"must": [
{
"multi_match": {
"fields": ["name"],
"query": "Chevrolet Hub Bearing",
"operator": "and"
}
}
]
}
}
}
and
运算符可确保搜索短语中的所有单词都必须出现在生成的文档中。仅此设置就可以为您提供所需的结果。