1

在我们基于 Solr 的搜索中,我们从使用短语开始。例如,当用户键入

blue dress

那么 Solr 查询将是

title:"blue dress" OR description:"blue dress"

我们现在要删除停用词。使用默认的 StopFilterFactory,查询

the blue dress

将匹配包含“blue dress”或“the blue dress”的文档。

但是,在键入时

blue the dress

那么它不匹配包含“蓝色连衣裙”的文档。

我开始怀疑我们是否不应该只使用单个词进行搜索。也就是将上面的用户搜索转化为

title:the OR title:blue OR title:dress OR description:the OR description:blue OR description:dress

不过,我有点不愿意这样做,因为它似乎在做 StandardTokenizerFactory 的工作。

这是我的 schema.xml:

<fieldType name="text_general" class="solr.TextField" positionIncrementGap="100">
  <analyzer type="index">
    <tokenizer class="solr.StandardTokenizerFactory"/>
      <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" />
      <filter class="solr.EdgeNGramFilterFactory" minGramSize="1" maxGramSize="25" />
    <filter class="solr.LowerCaseFilterFactory"/>
    <filter class="solr.SnowballPorterFilterFactory" language="English" />
  </analyzer>
  <analyzer type="query">
    <tokenizer class="solr.StandardTokenizerFactory"/>
      <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" />
      <filter class="solr.EdgeNGramFilterFactory" minGramSize="1" maxGramSize="25" />
    <filter class="solr.LowerCaseFilterFactory"/>
    <filter class="solr.SnowballPorterFilterFactory" language="English" />
  </analyzer>
</fieldType>

标题和描述字段都是text_general类型。

单项搜索是 Solr 中搜索的标准方式吗?在调用 Solr 之前,我是否通过对单词进行标记来暴露自己的问题(可能是性能问题)?也许从单个术语与短语的角度思考是错误的,我们应该让用户来决定?

4

2 回答 2

1

您偶然发现的事实是停用词过滤器阻止了停用词的索引,但它们的位置仍然被索引。类似空格的东西存储在出现停用词的索引中。

因此,当您将其放入索引时

蓝色连衣裙

它将被索引为

* 蓝色连衣裙

当您提交短语时也会发生同样的情况

“蓝色的裙子”

作为查询。将被视为

“蓝色连衣裙”

现在 Solr 比较这两个片段并且它不匹配,因为 * 位于错误的位置。

在 Solr 4.4 之前,这曾经通过 Pascal Dimassimo 所描述的设置enablePositionIncrements="true"StopFilterFactory 解决显然,正如SO 和 Solr 的 Jira 所讨论的那样,有一个重构确实破坏了 StopFilterFactory 上的该选项。


更新 阅读Extended Dis Max Query Parser的参考文档时,我发现了这个

停用词参数

一个布尔参数,指示在解析查询时是否应遵守查询分析器中配置的 StopFilterFactory:如果为 false,则忽略查询分析器中的 StopFilterFactory。

我会检查这是否有助于解决问题。

于 2015-08-24T11:04:44.003 回答
0

尽管如果将查询拆分为多个title:term语句,最初的方法可能会起作用,但这很容易出错(因为标记可能会被拆分到错误的位置)并且还会重复(可能很糟糕)由内置完成的工作 -在标记器中。

正确的方法是按原样维护初始查询并依靠 Solr 配置来正确处理它。这是有道理的,但困难在于我想指定我想搜索的字段。事实证明,使用默认查询解析器是没有办法做到这一点的,它被称为LuceneQParserPlugin(令人困惑的是,有一个名为fl的参数用于 Field List,用于指定返回的字段,而不是要搜索的字段)。

为了完整起见,必须提到可以通过使用copyField 配置来模拟要搜索的参数列表 schema.xml。我觉得这不够优雅也不够灵活。

优雅的解决方案是使用ExtendedDisMax 查询解析器,又名 edismax。有了它,我们可以按原样维护查询,并充分利用模式中的配置。在我们的例子中,它看起来像这样:

        SolrQuery solrQuery = new SolrQuery();
        solrQuery.set("defType", "edismax");
        solrQuery.set("q", query); // ie. "blue the dress"
        solrQuery.set("qf", "description title");

根据此页面

(e)Dismax 通常是面向用户的 Solr 应用程序的最佳首选查询解析器

如果这确实是默认选择,那将会有所帮助。

于 2015-08-24T13:13:09.147 回答