无法同时搜索两个字段,每个字段都使用自己的 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": []
}
}
以上查询是使用葡萄牙语术语完成的。即使索引有匹配的文档,也不会返回任何结果。
另一方面,一旦我:
从 'qf' 参数中删除 'body_texts_en'(在 solr 请求中),或者
从所有分析器中删除所有 solr.StopFilterFactory 过滤器,
正确返回匹配文档。
因此,这里的问题在于使用 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"必须与英文文本匹配。
关于此解决方案的一个警告是,它假设整个搜索将仅使用一种语言。混合英语和葡萄牙语搜索可能会失败,因为无法仅在一个文本字段中找到完整的单词集(不包括停用词)。
我定义了两个动态字段 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": []
}
}
以上查询是使用葡萄牙语术语完成的。即使索引有匹配的文档,也不会返回任何结果。 另一方面,一旦我:
从 'qf' 参数中删除 'body_texts_en'(在 solr 请求中),或者
从所有分析器中删除所有 solr.StopFilterFactory 过滤器,
正确返回匹配文档。
因此,这里的问题在于使用 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"必须与英文文本匹配。
关于此解决方案的一个警告是,它假设整个搜索将仅使用一种语言。混合英语和葡萄牙语搜索可能会失败,因为无法仅在一个文本字段中找到完整的单词集(不包括停用词)。