我找不到更好的标题,如果可能的话,我希望以后在你最终提出要求时更改它。
我的问题:
我有一个音乐艺术家的数据库。这些看起来像这样:"Dr. dre feat. akon"、"eminem & dr. dre"、"Dr. dre feat. ll cool j"、"Dr. Dre"、"Dr. dre feat. eminem & Skylar Grey"。我们只有两个字段:id 和 name。
在默认的模式 solr 核心上,我运行此查询:"q=dr. dre",结果还可以,但并不完美,如下所示:
- 德雷·费特博士。
- 阿姆和德雷博士
- 德雷博士
- 德雷博士
- 。
请注意,他们得到了完全相同的分数。
我想要的是将"dr. dre"作为第一个结果,然后是所有其他结果,如下所示:
- Dr. Dre
- <<-- Dr. Dre 是第一位
- 阿姆和德雷博士
- 德雷博士
- 德雷·费特博士。
- 。
我如何实现这一点?(过滤器、分词器、复制字段等并不重要。我无法更改 solr 中的代码,正如我在其他论坛上看到的那样)
谢谢。
有几种不同的方法可以让"dr. dre"结果首先出现。对于冗长的答案,我深表歉意,但正如Solr中经常发生的那样,答案取决于您的优先事项和需求。
这可能是多余的,但我想首先确保您看到每个结果的分数。你的问题没有完全清楚。当您进行查询时,您需要明确告诉 Solr 按分数降序对结果进行排序,尽管这可以
solrconfig.xml
中设置。我想您已经在这样做了,但为了确保,您可以尝试这样的查询:q="dr. dre"&fl=*,score&sort=score desc
.这将向您显示每个结果的计算分数,并首先对得分最高的结果进行排序。
规范
规范是一种灵活的选择,可以与Solr相当自然地配合使用。您的name
字段可能应该具有映射到fieldType
条目的type
值。fieldType
可能应该有class="solr.TextField"
,也不应该有omitNorms="true"
。除非您在名称字段中明确省略规范,否则在计算文档的分数时,Solr将考虑名称中有多少与您的搜索词匹配以及搜索词在名称中的匹配次数。"Dr. Dre"将获得最高分,因为名称中 100% 的单词与您的搜索匹配。
文档 wiki 上阅读规范并查看良好的通用文本fieldType
配置,或者在您下载的特定 Solr 版本的 Solr 文档中查看。依赖规范的好处是,除了相当容易实施之外,它们也是渐进的。因此,虽然"dr. dre"是最相关的记录,其名称100%与您的搜索相匹配,但"eminem & dr. dre"也比"a whole list of guys & and dr. dre"更相关,因为您的搜索词占名称的比例更大。
完全匹配
在Solr中,精确匹配是一个复杂的问题,主要是因为存在不同程度的"精确性",而在现实生活中很少需要真正的精确匹配。例如,如果您的记录名称为"dr. dre",那么"dr dre"(不带句点)是否足够接近以准确无误?是"德雷博士"吗?是"博士。 德雷"?
如果您决定实现完全匹配搜索,那么您可能希望在schema.xml
中设置一个 copyfield:
<copyField source="name" dest="exactName"/>
然后,您需要同时搜索这两个字段。如何执行此操作取决于您使用的查询分析器。如果您使用的是标准/lucene 查询解析器,则需要使用 OR 搜索来设置查询,(例如 q=name:"dr. dre" OR exactName:"dr. dre"^4
)。搜索词后面的"^4"使该匹配的重要性/相关性是查询中其他位置的匹配的 4 倍。如果您使用的是 Dismax 或扩展 Dismax 查询分析器,则可以访问较新的 qf
字段,该字段允许您提供用于搜索的字段列表,并将某些字段设置为比其他字段更重要。例如qf=exactName^4 name&q="dr. dre"
告诉Solr在两个字段中检查"dr. dre",但认为exactName字段中的匹配是名称字段中的匹配的4倍。(如果这适合您,则可以在solrconfig.xml
中设置默认qf
,因此不需要在每次查询时都重述它。
这使得 exactName 字段的fieldType
未定。如果您认为只有完全精确的匹配才有效,并且大小写或标点符号的变化使匹配不精确,那么您可以将 exactName 字段设置为字符串:
<field name="exactName" type="string" indexed="true" stored="false" multiValued="false"/>
但更有可能的是,您将希望允许在算作"精确"的内容中进行一些变化,在这种情况下,您将需要创建一个新的fieldType
,可能使用关键字分词器,它不会将确切的名称分解为多个索引令牌,而是将其保留为单个令牌。例如:
<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的搜索始终带有引号(即短语搜索)。否则,您的搜索将在与字段进行比较之前分解为单个字词,并且您的任何字词都不可能与整个索引字段匹配。这可能导致在字段中根本找不到任何匹配项,除非值不包含空格。如果您只是使用规范来控制具有更多标准标记化的 textField 中的相关性,则这不是问题。