25

我找不到更好的标题,如果可能的话,我希望稍后根据您的最终建议进行更改。

我的问题:

我有一个音乐艺术家的数据库。这些看起来像这样:“dr. dre feat. akon”、“eminem & dr. dre”、“dr. dre feat. ll cool j”、“dr. dre”、“dr. dre feat. eminem & skylar gray” . 我们只有两个字段:id 和 name。

在默认模式 solr 核心上,我运行以下查询:“q=dr.dre”,结果还可以,但并不完美,如下所示:

  • 博士。德雷壮举。阿孔
  • 阿姆和博士 dre
  • 博士。德雷壮举。会很酷j
  • 博士。dre
  • ...

请注意,他们得到了完全相同的分数。

我想要的是第一个结果是“dre 博士”,然后是所有其他结果,如下所示:

  • 博士。博士<<--博士。dre 是第一位的
  • 阿姆和博士 dre
  • 博士。德雷壮举。会很酷j
  • 博士。德雷壮举。阿孔
  • ...

我如何实现这一目标?(过滤器、标记器、复制字段等并不重要。我无法更改 solr 内的代码,正如我在其他一些论坛上所建议的那样)

谢谢。

4

1 回答 1

50

有几种不同的方法可以让“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% 的单词与您的搜索匹配。

您可以在 Solr 文档 wiki或下载的特定 Solr 版本的 Solr 文档中阅读规范并查看良好的通用文本fieldType配置。依赖规范的优势在于,除了相当容易实施之外,它们还具有进步性。因此,虽然“dr.dre”是相关的记录,其名称 100% 与您的搜索匹配,但“eminem & dr.dre”也将比“a whole list of guy & also dr.dre”相关,因为您的搜索词在名称中所占比例较大。

完全符合

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

如果您决定实施完全匹配搜索,那么您可能希望在您的schema.xml:

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

然后,您需要同时搜索这两个字段。如何执行此操作取决于您使用的查询解析器。如果您使用的是标准/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”,但认为确切名称字段中的匹配是名称字段中匹配的 4 倍。(如果这对您有用,qf则可以设置默认值,solrconfig.xml因此不需要在每次查询时都重新声明。)

这使得fieldTypeexactName 字段未确定。如果您认为只有完全精确的匹配才有效,并且大小写或标点符号的变化导致匹配不精确,那么您可以将 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 的搜索始终在其周围加上引号(即短语搜索)。否则,您的搜索将在与该字段进行比较之前被分解为单个术语,并且您的任何一个术语都不可能与整个索引字段匹配。这可能导致在字段中根本找不到任何匹配项,除非值不包含空格。如果您只是使用规范来控制具有更标准标记化的文本字段中的相关性,这不是问题。

于 2015-03-17T16:51:04.937 回答