Solr 查询:单个术语与短语

Solr Queries: Single Terms versus Phrases

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

blue dress

那么 Solr 查询将是

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

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

the blue dress

将匹配包含 "blue dress" 或 "the blue dress".

的文档

但是,在输入时

blue the dress

则不匹配包含"blue 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 之前通过标记化单词来暴露自己的问题(性能问题,也许)? 也许用单个术语和短语来思考是错误的,我们应该让用户自己决定?

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

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

the blue dress

它将被索引为

* blue dress

当你交出短语时也会发生同样的情况

"blue the dress"

作为查询。它将被视为

"blue * dress"

现在 Solr 比较这两个片段,但不匹配,因为 * 位置错误。

在 Solr 4.4 之前,这通常是通过在 StopFilterFactory as described by Pascal Dimassimo. Apparently there has been a refactoring that did break that option on the StopFilterFactory as discussed on SO and Solr's Jira.

中设置 enablePositionIncrements="true" 来解决的

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

The stopwords Parameter

A Boolean parameter indicating if the StopFilterFactory configured in the query analyzer should be respected when parsing the query: if it is false, then the StopFilterFactory in the query analyzer is ignored.

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

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

正确的方法是按原样维护初始查询,并依靠 Solr 配置来正确处理它。这是有道理的,但困难在于我想指定要搜索的字段。事实证明,使用默认查询解析器无法做到这一点,即所谓的 LuceneQParserPlugin (confusingly, there is a parameter called fl,用于字段列表,用于指定返回的字段,而不是要搜索的字段) .

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

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

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

根据this page

(e)Dismax generally makes the best first choice query parser for user facing Solr applications

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