将 Solr 4.10 升级到 6.3 后,搜索停止工作
After upgrading Solr 4.10 to 6.3 the search stopped working
我有一项升级 Solr
的任务,但之前从未使用过 Solr
。
目前我有下一个堆栈:Django 1.9.12 + Oscar 1.3 + Solr 6.3.0 + Haystack 2.5.1
我有一个由 Haystack
生成的模式,将其放在 managed-schema
文件中并根据 Whosebug 的答案进行了一些修改,因为 Solr
不想开始。
现在我有 Solr 可以启动,但无法通过网站的搜索字段找到任何东西(howower 使用 Solr 4.10,搜索按预期工作,没有任何问题)。
在以下部分的 solrconfig.xml
中:
<requestHandler name="/select" class="solr.SearchHandler">
<!-- default values for query parameters can be specified, these
will be overridden by parameters in the request
-->
<lst name="defaults">
<str name="echoParams">explicit</str>
<int name="rows">10</int>
</lst>
我尝试添加:
<str name="df">text</str>
<str name="q.op">AND</str>
之后搜索部分开始工作。
几个例子:
有这样的项目INTEL Pentium G3260 (CM8064601482506)
,搜索只用INTEL Pentium
或CM8064601482506
。如果我想查找 INTEL Pentium G3260
或 Pentium G3260
或 INTEL G3260
或 G3260
- 没有结果。
Search string:
AMD a8-6500;
Result:
没有显示(无结果)-> 应该找到 AMD a8-6500
Search string:
AMD;
Result:
显示所有 AMD 产品 -> 符合预期
如果我将 <str name="q.op">AND</str>
更改为 <str name="q.op">OR</str>
:
Search string:
AMD a8-6500; Result:
AMD A8-6500 显示所有 AMD 和
A8-6500 -> 应该只找到 AMD a8-6500
Search string:
a8-6500; Result:
AMD A8-6500 (AD650BOKA44HL) 和
INTEL Core™ i5 6500 -> 应该只找到 AMD a8-6500
我目前的 solrconfig.xml and managed-schema 在 GitHub。
作为我目前使用的索引字段EdgeNgramField
,即:
from haystack import indexes
class ProductIndexes(indexes.SearchIndex, indexes.Indexable):
text = indexes.EdgeNgramField(
document=True, use_template=True,
template_name='search/indexes/cpu/item_text.txt')
如何fix\normalize搜索?
更新 1:
仪表板日志页面的警告
[default] default search field in schema is text. WARNING: Deprecated,​ please use 'df' on request instead.
[default] query parser default operator is AND. WARNING: Deprecated,​ please use 'q.op' on request instead.
可以通过移除
来修复
<defaultSearchField>text</defaultSearchField>
<solrQueryParser defaultOperator="AND"/>
来自 managed-schema
个文件
更新二:
根据苏格拉底的回答,这里是最后的变化:
indexes.EdgeNgramField
在接下来的代码中:
class ProductIndexes(indexes.SearchIndex, indexes.Indexable):
text = indexes.EdgeNgramField(
document=True, use_template=True,
template_name='search/indexes/cpu/item_text.txt')
改为indexes.CharField
.
因为我有其他字段 indexes.CharField
,在 managed-schema
中我发现,这些字段使用类型 text_en
,并将 fieldType name="text_en"
替换为:
<fieldType name="text_en" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<tokenizer class="solr.StandardTokenizerFactory"/>
<!-- in this example, we will only use synonyms at query time
<filter class="solr.SynonymFilterFactory" synonyms="index_synonyms.txt" ignoreCase="true" expand="false"/>
-->
<!-- Case insensitive stop word removal.
-->
<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"/>
<!-- Optionally you may want to use this less aggressive stemmer instead of PorterStemFilterFactory:
<filter class="solr.EnglishMinimalStemFilterFactory"/>
-->
<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"/>
<!-- Optionally you may want to use this less aggressive stemmer instead of PorterStemFilterFactory:
<filter class="solr.EnglishMinimalStemFilterFactory"/>
-->
<filter class="solr.PorterStemFilterFactory"/>
</analyzer>
</fieldType>
由haystack
生成,至:
<fieldType name="text_en" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.StandardFilterFactory"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
<analyzer type="query">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.StandardFilterFactory"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
</fieldType>
- 在
sorlconfig.xml
代码中:
<requestHandler name="/select" class="solr.SearchHandler">
<lst name="defaults">
<str name="echoParams">explicit</str>
<int name="rows">10</int>
</lst>
</requestHandler>
更改为:
<requestHandler name="/select" class="solr.SearchHandler">
<lst name="defaults">
<str name="echoParams">explicit</str>
<int name="rows">10</int>
<str name="df">text</str>
<str name="q.op">AND</str>
</lst>
</requestHandler>
当你在 solr 请求中使用 q.op 时。 "q.op" 请求参数优先于此。
<solrQueryParser defaultOperator="OR"/>
带有 q.op 参数的示例查询:
http://localhost:8983/solr/collection1/select?indent=on&q.op=AND&q=for ipod&wt=json
If I want to find INTEL Pentium G3260 or Pentium G3260 or INTEL G3260 or G3260 - no results.
这与字段的分析和标记化方式有关。请参阅文档 here。
使用 ClassicTokenizerFactory 的标记化将表现如下:
输入:"Please, email john.doe@foo.com by 03-09, re: m37-xq."
输出:"Please"、"email"、"john.doe@foo.com"、"by"、“03-09”、"re"、"m37-xq"
使用 solr.EdgeNGramTokenizerFactory 的标记化将表现如下:
输入:"babaloo"
输出:"ba"、"bab"、"baba"、"babal"
在 schema.xml 中,您可以定义一个新的字段类型,或者像这样更新现有的字段类型:
<fieldType name="text" class="solr.TextField">
<analyzer type="index">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.StandardFilterFactory"/>
</analyzer>
</fieldType>
试一试,看看哪一个适合您的场景。您可能还想看看您给出的查询是如何规范化的。但这是一个很好的起点。
我有一项升级 Solr
的任务,但之前从未使用过 Solr
。
目前我有下一个堆栈:Django 1.9.12 + Oscar 1.3 + Solr 6.3.0 + Haystack 2.5.1
我有一个由 Haystack
生成的模式,将其放在 managed-schema
文件中并根据 Whosebug 的答案进行了一些修改,因为 Solr
不想开始。
现在我有 Solr 可以启动,但无法通过网站的搜索字段找到任何东西(howower 使用 Solr 4.10,搜索按预期工作,没有任何问题)。
在以下部分的 solrconfig.xml
中:
<requestHandler name="/select" class="solr.SearchHandler">
<!-- default values for query parameters can be specified, these
will be overridden by parameters in the request
-->
<lst name="defaults">
<str name="echoParams">explicit</str>
<int name="rows">10</int>
</lst>
我尝试添加:
<str name="df">text</str>
<str name="q.op">AND</str>
之后搜索部分开始工作。
几个例子:
有这样的项目
INTEL Pentium G3260 (CM8064601482506)
,搜索只用INTEL Pentium
或CM8064601482506
。如果我想查找INTEL Pentium G3260
或Pentium G3260
或INTEL G3260
或G3260
- 没有结果。Search string:
AMD a8-6500;Result:
没有显示(无结果)-> 应该找到 AMD a8-6500Search string:
AMD;Result:
显示所有 AMD 产品 -> 符合预期
如果我将 <str name="q.op">AND</str>
更改为 <str name="q.op">OR</str>
:
Search string:
AMD a8-6500;Result:
AMD A8-6500 显示所有 AMD 和 A8-6500 -> 应该只找到 AMD a8-6500Search string:
a8-6500;Result:
AMD A8-6500 (AD650BOKA44HL) 和 INTEL Core™ i5 6500 -> 应该只找到 AMD a8-6500
我目前的 solrconfig.xml and managed-schema 在 GitHub。
作为我目前使用的索引字段EdgeNgramField
,即:
from haystack import indexes
class ProductIndexes(indexes.SearchIndex, indexes.Indexable):
text = indexes.EdgeNgramField(
document=True, use_template=True,
template_name='search/indexes/cpu/item_text.txt')
如何fix\normalize搜索?
更新 1: 仪表板日志页面的警告
[default] default search field in schema is text. WARNING: Deprecated,​ please use 'df' on request instead.
[default] query parser default operator is AND. WARNING: Deprecated,​ please use 'q.op' on request instead.
可以通过移除
来修复 <defaultSearchField>text</defaultSearchField>
<solrQueryParser defaultOperator="AND"/>
来自 managed-schema
个文件
更新二: 根据苏格拉底的回答,这里是最后的变化:
indexes.EdgeNgramField
在接下来的代码中:class ProductIndexes(indexes.SearchIndex, indexes.Indexable): text = indexes.EdgeNgramField( document=True, use_template=True, template_name='search/indexes/cpu/item_text.txt')
改为
indexes.CharField
.因为我有其他字段
indexes.CharField
,在managed-schema
中我发现,这些字段使用类型text_en
,并将fieldType name="text_en"
替换为:
<fieldType name="text_en" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<tokenizer class="solr.StandardTokenizerFactory"/>
<!-- in this example, we will only use synonyms at query time
<filter class="solr.SynonymFilterFactory" synonyms="index_synonyms.txt" ignoreCase="true" expand="false"/>
-->
<!-- Case insensitive stop word removal.
-->
<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"/>
<!-- Optionally you may want to use this less aggressive stemmer instead of PorterStemFilterFactory:
<filter class="solr.EnglishMinimalStemFilterFactory"/>
-->
<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"/>
<!-- Optionally you may want to use this less aggressive stemmer instead of PorterStemFilterFactory:
<filter class="solr.EnglishMinimalStemFilterFactory"/>
-->
<filter class="solr.PorterStemFilterFactory"/>
</analyzer>
</fieldType>
由haystack
生成,至:
<fieldType name="text_en" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.StandardFilterFactory"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
<analyzer type="query">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.StandardFilterFactory"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
</fieldType>
- 在
sorlconfig.xml
代码中:
<requestHandler name="/select" class="solr.SearchHandler">
<lst name="defaults">
<str name="echoParams">explicit</str>
<int name="rows">10</int>
</lst>
</requestHandler>
更改为:
<requestHandler name="/select" class="solr.SearchHandler">
<lst name="defaults">
<str name="echoParams">explicit</str>
<int name="rows">10</int>
<str name="df">text</str>
<str name="q.op">AND</str>
</lst>
</requestHandler>
当你在 solr 请求中使用 q.op 时。 "q.op" 请求参数优先于此。
<solrQueryParser defaultOperator="OR"/>
带有 q.op 参数的示例查询:
http://localhost:8983/solr/collection1/select?indent=on&q.op=AND&q=for ipod&wt=json
If I want to find INTEL Pentium G3260 or Pentium G3260 or INTEL G3260 or G3260 - no results.
这与字段的分析和标记化方式有关。请参阅文档 here。
使用 ClassicTokenizerFactory 的标记化将表现如下: 输入:"Please, email john.doe@foo.com by 03-09, re: m37-xq." 输出:"Please"、"email"、"john.doe@foo.com"、"by"、“03-09”、"re"、"m37-xq"
使用 solr.EdgeNGramTokenizerFactory 的标记化将表现如下: 输入:"babaloo" 输出:"ba"、"bab"、"baba"、"babal"
在 schema.xml 中,您可以定义一个新的字段类型,或者像这样更新现有的字段类型:
<fieldType name="text" class="solr.TextField">
<analyzer type="index">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.StandardFilterFactory"/>
</analyzer>
</fieldType>
试一试,看看哪一个适合您的场景。您可能还想看看您给出的查询是如何规范化的。但这是一个很好的起点。