lucene 基于匹配标记比率的ElasticSearch评分

inb24sb2  于 2022-11-07  发布在  Lucene
关注(0)|答案(1)|浏览(220)

我正在使用Elasticsearch(1.7.3版,带有Java Transport Client)来搜索人名数据库。我利用了一系列可用的语音算法(DoubleMetaphone、RefinedSoundex等)来索引我的姓名字段并存储它们。然而,我需要的评分算法是计算输入令牌与索引中的令牌的接近度百分比。

例如:

以下文档在使用语音算法编制索引时:

{
  "FullName": "Christopher Cruickshank"
}

展开为(使用analyze api获取的输出):

{
  "tokens": [
    {
      "token": "C3090360109",
      "start_offset": 0,
      "end_offset": 11,
      "type": "<ALPHANUM>",
      "position": 1
    },
    {
      "token": "christopher",
      "start_offset": 0,
      "end_offset": 11,
      "type": "<ALPHANUM>",
      "position": 1
    },
    {
      "token": "K3936",
      "start_offset": 0,
      "end_offset": 11,
      "type": "<ALPHANUM>",
      "position": 1
    },
    {
      "token": "KRST",
      "start_offset": 0,
      "end_offset": 11,
      "type": "<ALPHANUM>",
      "position": 1
    },
    {
      "token": "C3903083",
      "start_offset": 12,
      "end_offset": 23,
      "type": "<ALPHANUM>",
      "position": 2
    },
    {
      "token": "cruickshank",
      "start_offset": 12,
      "end_offset": 23,
      "type": "<ALPHANUM>",
      "position": 2
    },
    {
      "token": "K3935",
      "start_offset": 12,
      "end_offset": 23,
      "type": "<ALPHANUM>",
      "position": 2
    },
    {
      "token": "KRKX",
      "start_offset": 12,
      "end_offset": 23,
      "type": "<ALPHANUM>",
      "position": 2
    }
  ]
}

现在,在搜索期间,当我查询:

{
              "match": {
                "FullName": {
                  "query": "Cristopher Krukshank",
                  "boost": 10.0
                }
              }
            }

我想做的是根据索引中匹配的标记的数量对结果进行评分。
例如:

(Number of matched tokens per term / Total number of expanded tokens per term) * Boost

虽然这在概念上是可行的,但我想知道是否有更好的方法来实现同样的目标。
此外,我倾向于在索引时间内增加很多复杂性和逻辑性(或者通过在字段中存储总令牌的计数)这样我的搜索逻辑将更简单。如果这是一个合理的方法,那么我想知道在索引过程中使用analyseapi是否有任何技术上的暗示,特别是当大量索引被用于数百万个名字时。我猜Analyze API将为每个原始标记和每个扩展标记(可能很大!)调用。
如果这不是一个合理的方法,那么请有人扔一些指针或分享一些经验?
我还考虑的另一个选项是在查询时调用analyze api,并使用“explain”选项将查询发送到elasticsearch,然后在explain部分进行字符串匹配,以计算出匹配的标记数。

rta7y2nd

rta7y2nd1#

我们是以间接的方式来做的。我正在寻找一个更好的方法,看到了你的帖子。
解决方案是当搜索“Cristopher Krukshank"时,第一个匹配项例如是:
小克里斯多佛·克鲁克申克”得分为10.0
然后,您将第一个结果“Cristopher Krukshank Jr.”再次搜索。当然,第一个结果将是“Cristopher Krukshank Jr.",但具有更高的分数,例如“20.0"。
因此,您知道最高分数是20,那么对于部分匹配,最终分数是“第一个分数/最高分数”,即10/20 = 0.5。最终分数将是0~1之间的值。1表示完全匹配。
一个问题是输入可能是一个命中任何东西的标记。例如,对于“Cristopher KrukshankXXXXX",XXXXX可能不是索引上的标记。因此,为了使其正确,我们必须使用标记的数量来重新计算得分。

相关问题