我正在尝试使用同义词过滤器来搜索短语。
peter=> spider man, spiderman, Mary Jane, .....
我使用默认配置。当我将这些同义词放入
synonym.txt
并重新启动 Solr 时,它似乎只能部分工作:它开始搜索 "spider"
、"man"
、"spiderman"
、"Mary"
和 "Jane"
但我想搜索什么是有意义的组合 - 例如 "spider man"
、"Mary Jane"
和 "spiderman"
。
是的,遗憾的是,这是一个众所周知的问题,因为 Solr 查询解析器在分析之前如何在空格上分解。因此,您不会在令牌流中看到“man”之前的“spider”,而是简单地看到每个单词本身。只是“蜘蛛”,没有任何前后,而只是“人”,没有任何前后。
这是因为大多数 Solr 查询表单将空格视为基本上的“OR”。搜索“spider OR man”,而不是查看全文,分析它以生成同义词,然后从中生成查询。有关更多背景信息,请参阅 这个问题有很多解决方案,包括以下:
例如,在我的fieldType/analyzer
schema.xml
中使用这一行:
<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 是两个单词,所以它可能(取决于我搜索的其他功能)单独或一起匹配这两个单词。通过选择单个单词形式进行规范化,我确保我的分词器不会尝试将其分解。
这是 Solr / Lucene 中的一个已知限制。本质上,您必须提供一种替代形式的标记化,以便将特定空格分隔的单词(即短语)视为单个单词。 实现此目的的一种方法是在客户端执行此操作 - 即在调用 Solr 的应用程序中,在索引时,保留同义词短语列表,并用替代项查找/替换这些短语值(例如删除空格或将其替换为不被视为令牌边界的分隔符)。
现在在您的 synonyms.txt 文件中您可以拥有(例如):
Hi HelloThere Wotcha => Hello
同样,在搜索时,将查询字符串中出现的“Hello There”替换为 HelloThere,然后它们将作为 Hello 的同义词进行匹配。
或者,您可以使用 LucidWorks 创建的AutoPhraseTokenFilter
(可在 github 上找到)。这是通过维护一个令牌流来实现的,这样它就可以计算出两个或多个连续令牌的组合是否与其中一个同义词短语匹配,如果不匹配,它就会丢弃第一个令牌,因为它与该短语不匹配。我不确定这会增加多少开销,但这似乎是一个很好的方法 - 默认情况下在 Solr 中作为 SynonymFilter 的一部分会很好。