Elasticsearch:仅匹配每个位置一次

时间:2014-01-16 14:01:47

标签: lucene position elasticsearch

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

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

示例:

我索引这样的文档。

{
    "field":"red car"
}

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

  • 位置1:“红色”
  • 位置2:“汽车”,“汽车”

我现在的解决方案:

为了确保所有位置都匹配,我也将索引最大位置。

{
    "field":"red car",
    "max_position": 2
}

我有一个自定义的相似性,它从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"
}

我的解决方案出现问题:

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

1 个答案:

答案 0 :(得分:0)

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

很遗憾,在您的情况下,您希望提供索引字词的100%匹配。为此,您必须下拉到Lucene级别并编写自定义(java - here's boilerplate you can fork)Similarity类,因为您需要访问未向Query DSL公开的低级索引信息:

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

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

由于查询和索引时间分析已经在此评分级别进行,因此索引术语的总数将已扩展为包含同义词,查询术语也应如此,从而避免误报“a car是上面的汽车“问题。