无法同时搜索两个字段,每个字段都使用自己的 solr.StopFilterFactory 过滤器

Not able to search two fields simultaneously each using its own solr.StopFilterFactory filter

我定义了两个动态字段 solr 5 模式:

<dynamicField name="*_texts_en" stored="true" type="text_en" multiValued="true" indexed="true"/>
<dynamicField name="*_texts_pt" stored="true" type="text_pt" multiValued="true" indexed="true"/>

对于英语和葡萄牙语文档,具有以下索引和查询分析器:

<fieldType name="text_en" class="solr.TextField" positionIncrementGap="100">
  <analyzer type="index">
<charFilter class="solr.HTMLStripCharFilterFactory"/>  
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_en.txt" />
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.EnglishPossessiveFilterFactory"/>
<filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
<filter class="solr.PorterStemFilterFactory"/>
  </analyzer>
  <analyzer type="query">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
<filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_en.txt" />
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.EnglishPossessiveFilterFactory"/>
<filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
<filter class="solr.PorterStemFilterFactory"/>
  </analyzer>
</fieldType>

<fieldType name="text_pt" class="solr.TextField" omitNorms="false">
  <analyzer type="index">
<charFilter class="solr.HTMLStripCharFilterFactory"/> 
    <tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_pt.txt" format="snowball" />
    <filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.PortugueseLightStemFilterFactory"/>
<filter class="solr.ASCIIFoldingFilterFactory" preserveOriginal="true"/> 
<filter class="solr.RemoveDuplicatesTokenFilterFactory" /> 
  </analyzer>
  <analyzer type="query">
    <tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_pt.txt" format="snowball" />
    <filter class="solr.LowerCaseFilterFactory"/>
<!-- <filter class="solr.BrazilianStemFilterFactory"/> -->
<filter class="solr.PortugueseLightStemFilterFactory"/>
<filter class="solr.ASCIIFoldingFilterFactory" preserveOriginal="false"/>
<filter class="solr.RemoveDuplicatesTokenFilterFactory" /> 
  </analyzer>
</fieldType>

文档可以是葡萄牙语和英语,它会使用类似于 'body_texts_en' 的内容作为英语字段。如果是葡萄牙语:'body_text_pt'.

但是,当在过滤器链中使用 solr.StopFilterFactory 时,我遇到了同时对两个字段进行搜索查询的问题。也就是我在不懂语言的情况下搜索某个查询时,我是这样查询solr的:

{
 "responseHeader": {
    "status": 0,
    "QTime": 1,
    "params": {
      "q": "suco de limão",
      "defType": "edismax",
      "indent": "true",
      "qf": " body_texts_pt  body_texts_en",
      "wt": "json",
      "lowercaseOperators": "true",
      "stopwords": "true",
      "_": "1430434475811"
    }
  },
  "response": {
    "numFound": 0,
    "start": 0,
    "docs": []
  }
}

以上查询是使用葡萄牙语术语完成的。即使索引有匹配的文档,也不会返回任何结果。 另一方面,一旦我:

正确返回匹配文档。

因此,这里的问题在于使用 solr.StopFilterFactory 并同时查询两个字段,每个字段都有自己的 solr.StopFilterFactory 使用(如上所示)。

是否有希望让上面的查询按预期工作?

提前致谢。

编辑(Ruby 我根据@frances 对他的解决方案 2 的回复编写的函数):

def multiple_language_query_solr(q) 
fields = {'title' => 2, 'body' => 1}
query = []
I18n.available_locales.each do |locale|
  locale = locale.to_s.split('-').first
  fields.each do |field, boost|
    field = "#{field}_texts_#{locale}" + (boost > 1 ? "^#{boost}" : '') + ':' 
    sentence = q.split(' ').map do |word|
      field + word
    end.join(' AND ')
    query << "(#{sentence})"        
  end
end
query.join(' OR ')
end

谨致问候, 埃里克

这可能是也可能不是你的问题,但我想我知道这里发生了什么。您没有指定 mm (Minimum Should Match) 值,我怀疑该值至少设置为“3”或“70%”。 (顺便说一句,将来如果您将参数 echoParams=all 添加到您的 Solr 查询中,在您的 solrconfig.xml 中设置的在搜索中处于活动状态的参数也将被返回,给出一个更完整的搜索图片。)

当您仅搜索葡萄牙语文本字段时,查询解析器会像这样扩展您的查询:

( body_texts_pt:suco ) ( body_texts_pt:limão )

因为 "de" 在您的葡萄牙语停用词过滤器中,所以它已从您的搜索中完全消除,并且您的剩余字词中有两个 (100%) 匹配。当您的搜索同时使用这两个字段时,它将像这样展开:

( body_texts_pt:suco | body_texts_en:suco ) ( body_texts_en:de )
( body_texts_pt:limão | body_texts_en:limão )

这次 "de" 没有从您搜索的 所有 搜索字段中删除,因此它仍然是您搜索中的一个词。但因为它已从葡萄牙语文本的搜索中排除,它只能与英文文本匹配。结果:三分之二 (~66%) 的字词匹配,而不是二分之二。如果你的 mm 值是严格的,那么(向 Meat Loaf 道歉)三分之二可能不会削减它。

解决方案?

1.关闭停用词过滤(简单的解决方案 - 推荐)

当停用词过滤器配置在 所有 个搜索字段中匹配时,此问题已完全解决。由于您无法在英语和葡萄牙语字段中应用一组合理的统一停用词,因此根本不使用停用词。停用词过滤通常不会像人们想象的那样对索引效率产生太大影响。我建议在停用所有停用词过滤的情况下重建您的索引,以查看这是否会在速度上产生明显的差异。

2。预处理查询字符串(比较复杂)

您使用的 Extended Dismax Query Parser (edismax). The main difference between this and the Dismax Query Parser (dismax) 支持 logical/boolean 查询。如果您自己扩展查询,您可以创建适合您的逻辑结构。对于搜索:suco de limão,实际发送到 Solr 的预处理搜索可能是:

(body_texts_pt:suco AND body_texts_pt:de AND body_texts_pt:limão) OR
       (body_texts_en:suco AND body_texts_en:de AND body_texts_en:limão)

对于此查询,词条 body_texts_pt:de 被停用词过滤器删除,因此词条 "suco" 和 "limão" 必须与葡萄牙语文本匹配,单词"suco"和"de"和"limão"必须与英文文本匹配。

关于此解决方案的一个警告是,它假设整个搜索将仅使用一种语言。混合英语和葡萄牙语搜索可能会失败,因为无法仅在一个文本字段中找到完整的单词集(不包括停用词)。