Solr:准确匹配的得分高于部分匹配

Posted

技术标签:

【中文标题】Solr:准确匹配的得分高于部分匹配【英文标题】:Solr: Scoring exact matches higher than partial matches 【发布时间】:2014-12-09 11:51:58 【问题描述】:

在一个非常简单的例子中,我有三个文件名为“Lark”、“Larker”和“Larking”(没有文件扩展名)。在 solr 中,我索引这三个文档,将文件名映射到“标题”字段。当我搜索“Lark”时,所有三个文档都会返回(这就是我想要的),但它们都给出了相同的分数。我希望“Lark”得分最高,因为它与我的查询完全匹配,而其他的则排在后面。

<field name="title" type="text_general" indexed="true" stored="true" multiValued="false"/>

 

<fieldType name="text_general" class="solr.TextField" positionIncrementGap="100">
  <analyzer type="index">
    <tokenizer class="solr.StandardTokenizerFactory"/>
    <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" />
    <filter class="solr.LowerCaseFilterFactory"/>
    <filter class="solr.EdgeNGramFilterFactory" minGramSize="2" maxGramSize="15" side="front"/>
  </analyzer>
  <analyzer type="query">
    <tokenizer class="solr.StandardTokenizerFactory"/>
    <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" />
    <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
    <filter class="solr.LowerCaseFilterFactory"/>
  </analyzer>
</fieldType>

我相信他们获得相同分数的原因是因为在索引时使用了EdgeNGramFilterFactory。每个文档都被索引为“La”、“Lar”、“Lark”,其中两个文档(“Larker”和“Larking”)被索引了一些额外的变体。因此,实际上每个文档都与查询“Lark”完全匹配。我想要某种执行查询的方式,其中术语“Lark”将返回所有三个文档,但标题为“Lark”的文档的返回值高于其他文档。

查询调试结果:

<lst name="debug">
  <str name="rawquerystring">Lark</str>
  <str name="querystring">Lark</str>
  <str name="parsedquery">text:lark</str>
  <str name="parsedquery_toString">text:lark</str>
  <lst name="explain">
    <str name="543d6ee4cbb33c26bbcf288b/xxnullxx/543d6ef9cbb33c26bbcf2892">
2.7104912 = (MATCH) weight(text:lark in 0) [DefaultSimilarity], result of:
  2.7104912 = fieldWeight in 0, product of:
    1.4142135 = tf(freq=2.0), with freq of:
      2.0 = termFreq=2.0
    3.8332133 = idf(docFreq=3, maxDocs=68)
    0.5 = fieldNorm(doc=0)
</str>
    <str name="543d6ee4cbb33c26bbcf288b/xxnullxx/543d6ef9cbb33c26bbcf2893">
2.7104912 = (MATCH) weight(text:lark in 1) [DefaultSimilarity], result of:
  2.7104912 = fieldWeight in 1, product of:
    1.4142135 = tf(freq=2.0), with freq of:
      2.0 = termFreq=2.0
    3.8332133 = idf(docFreq=3, maxDocs=68)
    0.5 = fieldNorm(doc=1)
</str>
    <str name="543d6ee4cbb33c26bbcf288b/xxnullxx/543d6ef9cbb33c26bbcf2894">
2.7104912 = (MATCH) weight(text:lark in 2) [DefaultSimilarity], result of:
  2.7104912 = fieldWeight in 2, product of:
    1.4142135 = tf(freq=2.0), with freq of:
      2.0 = termFreq=2.0
    3.8332133 = idf(docFreq=3, maxDocs=68)
    0.5 = fieldNorm(doc=2)
</str>

【问题讨论】:

奇怪的是,您在所有 3 个文档中都获得了相同的分数。 fieldNorm 对于Larking 应该是最低的,对于Lark 应该是最高的,所以Lark 应该得到最高分。您可以使用 debugQuery=on&amp;wt=xml 重新运行查询并检查您为每个文档获得的 fieldNorm 吗? 已添加,@arun。 fieldNorm 三个都一样。 【参考方案1】:

为了提高精确匹配,您可以创建一个名为“exact_title”的新字段,其中包含一个没有 EdgeNGramFilterFactory 的新类型“text_exact”。

在您的架构中,您可以使用以下行:

<copyField source="title" dest="exact_title"/> 

将标题复制到exact_title。

然后针对两个字段(title 和exact_title)运行您的查询。如果查询匹配一个确切的标题,具有该确切标题的文档将获得比其他文档更高的分数,并会上升到顶部。

【讨论】:

【参考方案2】:

也许晚了,但您也可以使用KeywordRepeatFilterFactory 而不创建新字段。 Solr documentation 是这样描述的:

一个重复的问题是“我怎样才能让原始术语做出贡献 比词干版本更重要”?在 Solr 4.3 中, 已添加 KeywordRepeatFilterFactory 来协助此操作 功能。此过滤器为每个输入标记发出两个标记,一个 其中标有关键字属性。尊重的词干 关键字属性将通过标记为无 改变。所以这个过滤器的效果是索引 原词和词干版本。

【讨论】:

以上是关于Solr:准确匹配的得分高于部分匹配的主要内容,如果未能解决你的问题,请参考以下文章

Solr - termfreq部分匹配

solr如何让全词匹配结果在最前面

倾向得分匹配(PSM)的原理以及应用

将部分案例与 Python 字典匹配

TDK优化技巧

MySQL MATCH() AGAINST() FULLTEXT Index - 结合短语匹配实现部分字符串匹配