【问题标题】:Match query not return exacth match as first row匹配查询不返回精确匹配作为第一行
【发布时间】:2019-07-25 03:11:07
【问题描述】:

我在elasticsearch中有数据,字段为fullName:

  1. 约翰·多伊·多伊
  2. 约翰·多伊
  3. 埃里克·约翰·多伊

当我对fullName 进行匹配查询时,使用此查询

{
    "from": 0,
    "size": 20,
    "query": {
        "bool": {
            "must": [
                {
                    "match": {
                        "fullName": {
                            "query": "John Doe",
                            "operator": "AND",
                            "fuzziness": "AUTO"
                        }
                    }
                }
            ]
        }
    }
}

我希望得到John Doe(完全匹配)作为第一个结果。 相反,返回的值是这样的:

  1. 约翰·多伊·多伊
  2. 埃里克·约翰·多伊
  3. 约翰·多伊

完全匹配的结果是最低的。

我应该怎么做才能将完全匹配放入第一个结果中? 我不能使用term 查询,因为我仍然需要对fullName 进行模糊匹配

谢谢

【问题讨论】:

  • 这个answer 可能会对你有所帮助。
  • @NishantSaini 建议的答案提供了非常有价值的信息,但它不处理重复的术语。 “John Doe”仍将在“John Doe”之后。

标签: elasticsearch


【解决方案1】:

错误的顺序是由 2 个不同的问题造成的。

修正第二个和第三个文档的顺序

第二个和第三个文档之间的顺序错误可能是由于分片。如果您使用单个分片,您将获得以下顺序:

  • 约翰·多伊·多伊
  • 约翰·多伊
  • 埃里克·约翰·多伊

您可以阅读this article 来解释原因。但是,如果您在每个分片中有很多文档,则不应该有这个问题。如果您想确保统计信息始终正确,您可以在搜索查询参数中使用_search?search_type=dfs_query_then_fetch。

修正第一个和第二个文档的顺序

这有点棘手。默认的 elasticsearch 相似度(即 BM25)将如果一个词出现多次则增加分数。在您的情况下,“Doe”出现两次,因此它的分数更高。要更改此行为,您必须使用custom similarity。

您有两种解决方案:

  • 根据现有的相似性写一个scripted similarity,以丢弃重复术语的重要性
  • 配置默认的 BM25 相似度以降低重复词条的重要性

要在现有索引上创建自定义相似度,您必须:

  • close the index
  • 使用_settings 端点添加相似性。
  • 重新打开索引

您也可以在创建索引时添加相似度。在示例中,我将始终创建一个新索引。

要使用相似度,您可以将其设置为default similarity 或专门使用相似度创建子字段。请注意,更改默认相似度会影响您在索引中的所有查询。在您的情况下,我认为创建子字段会更好。

解决方案 1:创建脚本相似性

使用此解决方案,您将使用脚本相似性消除重复术语的影响。此脚本基于 TFIDF。

PUT /<INDEX>
{
    "settings": {
        "index": {
            "similarity": {
                "scripted_tfidf": {
                    "type": "scripted",
                    "script": {
                        "source": "return query.boost * (Math.log((field.docCount+1.0)/(term.docFreq+1.0)) + 1.0) / Math.sqrt(doc.length);"
                    }
                }
            }
        }
    },
    "mappings": {
        "properties": {
            "fullName": {
                "type": "text",
                "fields": {
                    "custom_similarity": {
                        "type": "text",
                        "similarity": "scripted_tfidf"
                    }
                }
            }
        }
    }
}

评论

  • TFIDF 是一种已弃用的相似性,但由于其具有重复术语的行为,它已被弃用。由于我们消除了重复术语的影响,所以没问题。

  • 由于重复的术语被完全丢弃,因此使用此解决方案,完全匹配始终是第一个,但“John Doe Doe”和“Eric John Doe”将具有相同的分数。

方案二:配置BM25相似度

您可以通过配置BM25 similarity 来更改相似行为。它有两个参数k1和b。

  • k1:定义重复项的重要性。您想降低此值;
  • b:定义赋予术语数量的重要性。您想增加此值。
PUT /<INDEX>
{
    "settings": {
        "index": {
            "similarity": {
                "bm_25_custom": {
                    "type": "BM25",

                    // Update k1 and b values for bm25
                    "k1": "0.1",     
                    "b": "1.0"
                }
            }
        }
    },
    "mappings": {
        "properties": {
            "fullName": {
                "type": "text",
                "fields": {

                    // Add a subfield using the similarity defined previously
                    "custom_similarity": {
                        "type": "text",
                        "similarity": "bm_25_custom"
                    }
                }
            }
        }
    }
}

评论

  • 如果您设置k1 = 0,在计算分数时,重复项和项数都将被丢弃。您的第一份和第二份文件将具有相同的分数,并且顺序将是随机的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-04-30
    • 2017-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-17
    • 1970-01-01
    相关资源
    最近更新 更多