【问题标题】:Multi-word synonym search in SolrSolr 中的多词同义词搜索
【发布时间】:2015-04-16 16:07:05
【问题描述】:

我正在尝试使用同义词过滤器来搜索短语。

peter=> spider man, spiderman, Mary Jane, .....

我使用默认配置。当我将这些同义词放入 synonym.txt 并重新启动 Solr 时,它似乎只能部分工作:它开始搜索 "spider""man""spiderman""Mary""Jane",但我想搜索的是什么是有意义的组合 - 例如"spider man""Mary Jane""spiderman"

【问题讨论】:

标签: solr synonym


【解决方案1】:

是的,很遗憾,这是一个众所周知的问题,因为 Solr 查询解析器如何在分析之前分解空格。因此,您不必在令牌流中看到“人”之前的“蜘蛛”,而是简单地看到每个单词。只是“蜘蛛”,之前/之后什么都没有,只是“人”,之前/之后什么都没有。

这是因为大多数 Solr 查询表单将空格基本上视为“或”。搜索“spider OR man”而不是查看全文,对其进行分析以生成同义词,然后从中生成查询。

更多背景信息,this blog post

这个问题有很多解决方案,包括以下:

  • hon-lucene-synonyms。该插件在生成多个字段的 edismax 查询之前运行分析器。它有点像黑盒,我发现它可以生成一些复杂的查询表单,这些表单会产生奇怪的性能和相关性错误。
  • Lucidwork's autophrase query parser 通过选择性地自动表达,这个插件可以让你指定不应该被分解成 OR 查询并且可以应用同义词扩展的关键短语(蜘蛛侠)
  • 开源连接的Match query parser。在搜索字段之前使用查询指定的分析器搜索单个字段。还将多词同义词搜索为短语。我最喜欢,但免责声明:我是作者 :)
  • Rene Kriegler 的Querqy -- Querqy 是一个用于查询预处理规则的 Solr 插件。这些规则可以识别您的关键短语并将查询重写为非多词形式。
  • 自己动手:学习编写自己的 query parser plugin 并随心所欲地处理问题。

【讨论】:

  • 您还应该提到特殊字符和PatternReplaceFilterFactory 字符的使用(例如spiderman, spider man, peter => peter, spiderman, spider_man,然后将_ 替换为` `。它不适用于所有情况,但是它确实适用于很多。(从提到您的匹配查询解析器的同一篇博客文章中窃取。)
【解决方案2】:

对于此类问题,我通常的策略是使用同义词过滤器,而不是扩展搜索以包含所有可能的同义词,而是规范化为单一形式。我在索引和查询字段分析中这样做。

例如,在schema.xml 中的fieldType/analyzer 块中使用此行:

<filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="false"/>

(注意expand="false"
...以及我的synonyms.txt 中的这一行:

spiderman, spider man, Mary Jane => peter

这样我可以确保这四个值中的任何一个都将被编入索引并且搜索为“peter”。例如,如果源文档提到“The Amazing Spider Man”,它将被索引为“The Amazing peter”。当用户搜索“Mary Jane”时,它会改为搜索“peter”,因此会匹配

这里重要的是,因为“Mary”不是逗号分隔的同义词之一,所以如果它出现时没有跟随“Jane”,它不会改变。所以搜索“Mary is Amazing”实际上会搜索“Mary is Amazing”,并且不会匹配到文档。

其中一个重要的细节是,我选择了一个只有一个词的规范化形式(例如“peter”)。我可以这样组织:

peter, spiderman, spider man => Mary Jane

但是因为 Mary Jane 是两个词,它可能(取决于我搜索的其他功能)将这两个词分别匹配以及一起匹配。通过选择一个单词形式进行规范化,我确保我的分词器不会尝试分解它。

【讨论】:

  • 感谢您的信息(虽然我可能需要更多时间来理解这一点),我不能做的一件事是重新索引所有文档。我只能编辑 synonym.txt 并重新启动 SOLR
  • 啊。然后您将无法在索引时应用规范化,这是我策略的重要组成部分。缺少这一点,选择就更少了。将更多的搜索作为显式短语搜索可能会有所帮助。换句话说,不要搜索peter,而是尝试搜索"peter"。这并不理想,因为您可能不想一直使用短语搜索,但在某些情况下,如果您可以包含引号,它可能会对您有所帮助。
  • 因为这在应用过滤器工厂之前被标记化,'spider' 和 'man' 不是两个不同的标记吗?在这种情况下,“蜘蛛侠”永远不会匹配提供给过滤器的令牌。看着Solr Doc 这说:这个过滤器做同义词映射。在同义词列表中查找每个标记,如果找到匹配项,则发出同义词代替标记。设置新标记的位置值,使它们都出现在与原始标记相同的位置。
【解决方案3】:

这是 Solr / Lucene 中的一个已知限制。本质上,您必须提供另一种标记化形式,以便将特定空格分隔的单词(即短语)视为单个单词。 实现此目的的一种方法是在客户端执行此操作 - 即在调用 Solr 的应用程序中,在编制索引时,保留同义词短语列表并用替代项查找/替换这些短语值(例如删除空格或将其替换为不被视为标记边界的分隔符)。

例如如果您想在同义词中使用“Hello There”作为短语,则在索引时将其替换为“HelloThere”。

现在在您的 synonyms.txt 文件中,您可以拥有(例如):

Hi HelloThere Wotcha => Hello

类似地,当您搜索时,将查询字符串中出现的“Hello There”替换为 HelloThere,然后它们将被匹配为 Hello 的同义词。

或者,您可以使用 LucidWorks 创建的 AutoPhraseTokenFilter,在 github 上可用。这通过维护一个标记流来工作,以便它可以计算出两个或多个连续标记的组合是否与同义词短语中的一个匹配,如果不匹配,则将第一个标记丢弃为与短语不匹配。我不确定这会增加多少开销,但这似乎是一个不错的方法 - 默认情况下,在 Solr 中将其作为 SynonymFilter 的一部分会很好。

【讨论】:

    猜你喜欢
    • 2023-04-04
    • 2022-11-25
    • 2015-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-26
    • 1970-01-01
    相关资源
    最近更新 更多