Elasticsearch:仅匹配每个位置一次

Dan*_*nyG 6 lucene position elasticsearch

在我的Elasticsearch索引中,我有在同一位置有多个令牌的文档.

当我在每个位置匹配至少一个令牌时,我想要取回一份文件.令牌的顺序并不重要.我怎么能做到这一点?我使用Elasticsearch 0.90.5.

例:

我索引这样的文档.

{
    "field":"red car"
}
Run Code Online (Sandbox Code Playgroud)

我使用同义词令牌过滤器,在与原始令牌相同的位置添加同义词.所以现在在现场,有2个职位:

  • 位置1:"红色"
  • 位置2:"汽车","汽车"

我现在的解决方案:

为了能够确保所有位置匹配,我也将索引最大位置.

{
    "field":"red car",
    "max_position": 2
}
Run Code Online (Sandbox Code Playgroud)

我有一个从DefaultSimilarity扩展的自定义相似性,并返回1 tf(),idf()和lengthNorm().得分是该字段中匹配项的数量.

查询:

{
    "custom_score": {
        "query": {
             "match": {
                 "field": "a car is an automobile"
             }
        },
        "_script": "_score*100/doc[\"max_position\"]+_score"
    },
    "min_score":"100"
}
Run Code Online (Sandbox Code Playgroud)

我的解决方案有问题:

上述搜索不应与文档匹配,因为查询字符串中没有标记"red".但它匹配,因为Elasticsearch将汽车和汽车的匹配计算为两个匹配,得分为2,这导致脚本得分为102,满足"min_score".

Pet*_*ses 0

如果您需要保证与查询词100% 匹配,您可以使用minimum_should_match. 这是比较常见的情况。


不幸的是,在您的情况下,您希望提供索引术语的 100% 匹配。为此,您必须下降到 Lucene 级别并编写一个自定义(java -这里是您可以 fork 的样板)相似性类,因为您需要访问未暴露给 Query DSL 的低级索引信息:

在查询评分器中扫描的每个文档/字段:

然后,您的自定义相似度(您甚至可以扩展 DefaultSimilarity)将需要检测术语匹配<总术语的查询,并将其分数乘以零。

由于查询和索引时间分析已经发生在这个评分级别,索引术语的总数将已经扩展到包括同义词,查询术语也应该如此,从而避免了上面的误报“汽车是汽车”问题。