SOLR完全匹配提升包含完全匹配的文本

时间:2015-03-17 15:29:07

标签: solr exact-match solr-boost

我找不到一个更好的标题,我希望在你最终的消遣后尽可能改变它。

我的问题:

我有一个音乐艺术家的数据库。这些看起来像这样:"博士。 dre feat。 akon"," eminem&博士。 dre","博士。 dre feat。冷静j","博士。 dre","博士。 dre feat。埃米纳姆skylar grey"。我们只有两个字段:id和name。

在默认架构solr核心上,我运行此查询:" q = dr。 DRE"结果还可以但并不完美,看起来像这样:

  • 博士。 dre feat。阿肯
  • eminem&博士。 DRE
  • 博士。 dre feat。 ll cool j
  • 博士。 DRE
  • ...

请注意,他们得分完全相同。

我想要的是拥有"博士。 DRE"作为第一个结果,然后是所有其他结果,如下:

  • 博士。 dre << - dr。 dre是第一个
  • eminem&博士。 DRE
  • 博士。 dre feat。 ll cool j
  • 博士。 dre feat。阿肯
  • ...

我如何实现这一目标? (过滤器,标记器,复制字段等等并不重要。我无法更改solr中的代码,因为我已在其他论坛上看到过建议)

感谢。

1 个答案:

答案 0 :(得分:34)

有几种不同的方法可以让“dr.dre”结果首先出现。我为冗长的答案道歉,但正如Solr经常发生的那样,答案取决于您的优先事项和需求。

  

这可能是多余的,但我想首先确保您看到每个结果的分数。你的问题并没有完全清楚。在进行查询时,您需要明确告诉Solr按结果降序对结果进行排序,但这可以在solrconfig.xml中设置。我想你已经这样做了,但为了确保你可以尝试这样的查询:q="dr. dre"&fl=*,score&sort=score desc。这将显示每个结果的计算得分,并首先对结果进行排序。

规范

规范是一种灵活的选择,可以很自然地与Solr合作。您的name字段应该具有映射到type条目的fieldType值。 fieldType可能应该有class="solr.TextField",而且不应该有omitNorms="true" 。除非您在名称字段中明确省略规范,否则Solr会在计算文档分数时考虑名称中您的搜索字词的多少以及搜索字词与名称匹配的次数。 “dr.dre”得分最高,因为名称中100%的单词与您的搜索匹配。

您可以阅读有关规范的信息,并在the Solr documentation wiki或您下载的Solr文档中查看有关特定Solr版本的良好通用文本fieldType配置。依赖规范的优点是,除了相当容易实现之外,它们是渐进的。因此,虽然“dr.dre”将是相关记录,其100%的名称与您的搜索匹配,“eminem& dr.dre”也将更多相关因为你的搜索字词占名称的比例较大,所以比“整个人名单还有博士”更胜一筹。

完全匹配

完全匹配在Solr中是一个复杂的问题,主要是因为存在不同程度的“精确度”,并且在现实生活中很少需要真正完全匹配。例如,如果您的记录名称为“dr.dre”,那么“dr dre”(没有句点)是否足够接近准确?是“Dr. Dre”吗?是“dr.dre”吗?

如果您决定实施完全匹配搜索,那么您可能希望在schema.xml中设置一个副本字段:

<copyField source="name" dest="exactName"/>

然后,您将要同时搜索这两个字段。如何执行此操作取决于您使用的查询解析器。如果您使用standard/lucene查询解析器,则需要使用OR搜索设置查询(例如q=name:"dr. dre" OR exactName:"dr. dre"^4)。搜索词后面的“^ 4”使得该匹配与查询中其他位置的匹配重要/相关4倍。如果您使用的是DismaxExtended Dismax查询解析器,则可以访问较新的qf字段,该字段允许您提供用于搜索的字段列表,以及设置有些人比其他人更重要。例如qf=exactName^4 name&q="dr. dre"告诉Solr在两个字段中检查“dr.dre”,但是将exactName字段中的匹配视为与name字段中的匹配相关的4倍。 (如果这适合您,则可以在qf中设置默认solrconfig.xml,因此不需要对每个查询进行重新设置。)

这使得exactName字段的fieldType未定。如果您认为只有完全精确的匹配才有效,并且大小写或标点符号的变化会使匹配不准确,那么您可以将exactName字段设置为字符串:

<field name="exactName" type="string" indexed="true" stored="false" multiValued="false"/>

但更有可能的是,你会想要允许一些变化为“精确”,在这种情况下你需要制作一个新的fieldType,可能使用Keyword Tokenizer,这不会将确切的名称分成多个索引标记,但将其保留为单个标记。例如:

<fieldType name="exactish" class="solr.TextField">
  <analyzer>
   <tokenizer class="solr.KeywordTokenizerFactory"/>
   <filter class="solr.LowerCaseFilterFactory"/>
  </analyzer> 
</fieldType>

<field name="exactName" type="exactish" indexed="true" stored="false" multiValued="false"/>

这个非常基本的示例仅包括将整个名称保留为单个标记的关键字标记符,以及小写过滤器,以确保大写和小写之间的差异不相关。如果您希望您的完全匹配能够容忍任何其他条件,则需要修改fieldType的分析。

重要提示:在搜索字符串字段或具有关键字标记符的文本字段时,最好确保发送给Solr的搜索始终在其周围添加引号(即短语搜索)。否则,在与字段进行比较之前,您的搜索将被分解为单个字词,并且您的字词的一个可能与整个索引字段不匹配。这可能导致永远不会在字段中找到任何匹配,除非值无论如何都不包含空格。如果您只是使用Norms来控制textField中的相关性以及更多标准标记化,那么这不是问题。