Xav*_*ois 7 solr tokenize phrase
在Solr(3.3)中,是否可以通过字母逐字母搜索EdgeNGramFilterFactory并且对短语查询敏感?
例如,我正在寻找一个字段,如果包含"contrat informatique",将在用户输入时找到:
目前,我做了这样的事情:
<fieldtype name="terms" class="solr.TextField">
<analyzer type="index">
<charFilter class="solr.MappingCharFilterFactory" mapping="mapping-ISOLatin1Accent.txt"/>
<filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1"/>
<tokenizer class="solr.LowerCaseTokenizerFactory"/>
<filter class="solr.EdgeNGramFilterFactory" minGramSize="2" maxGramSize="15" side="front"/>
</analyzer>
<analyzer type="query">
<charFilter class="solr.MappingCharFilterFactory" mapping="mapping-ISOLatin1Accent.txt"/>
<filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1"/>
<tokenizer class="solr.LowerCaseTokenizerFactory"/>
</analyzer>
</fieldtype>
Run Code Online (Sandbox Code Playgroud)
...但是短语查询失败了.
当我在solr admin中查看模式分析器时,我发现"contrat informatique"生成了以下标记:
[...] contr contra contrat in inf info infor inform [...]
Run Code Online (Sandbox Code Playgroud)
因此查询使用"contrat in"(连续令牌),但不使用"contrat inf"(因为这两个令牌是分开的).
我很确定任何类型的词干都可以用短语查询,但我找不到正确的过滤器标记器来使用之前EdgeNGramFilterFactory.
由于查询slop参数= 0,默认情况下,精确短语搜索不起作用.在搜索短语"Hello World"时,它会搜索具有连续位置的词语.我希望EdgeNGramFilter有一个参数来控制输出定位,这看起来像一个老问题.
通过将qs参数设置为某个非常高的值(超过ngrams之间的最大距离),您可以获得短语.这部分地解决了允许短语但不精确的排列的问题.因此,搜索"contrat informatique"会匹配"...被放弃的合同.信息......"等文字.

为了支持精确的短语查询,我最终使用ngrams的单独字段.
所需步骤:
定义单独的字段类型以索引常规值和克:
<fieldType name="text" class="solr.TextField" omitNorms="false">
<analyzer>
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
</fieldType>
<fieldType name="ngrams" class="solr.TextField" omitNorms="false">
<analyzer type="index">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.EdgeNGramFilterFactory" minGramSize="2" maxGramSize="15" side="front"/>
</analyzer>
<analyzer type="query">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
</fieldType>
Run Code Online (Sandbox Code Playgroud)
在索引时告诉solr 复制字段:
您可以为每个字段定义单独的ngrams反射:
<field name="contact_ngrams" type="ngrams" indexed="true" stored="false"/>
<field name="product_ngrams" type="ngrams" indexed="true" stored="false"/>
<copyField source="contact_text" dest="contact_ngrams"/>
<copyField source="product_text" dest="product_ngrams"/>
Run Code Online (Sandbox Code Playgroud)
或者您可以将所有ngrams放入一个字段:
<field name="heap_ngrams" type="ngrams" indexed="true" stored="false"/>
<copyField source="*_text" dest="heap_ngrams"/>
Run Code Online (Sandbox Code Playgroud)
请注意,在这种情况下,您将无法分离助推器.
最后一件事是在查询中指定ngrams字段和助推器.一种方法是配置您的应用程序.另一种方法是在solrconfig.xml中指定"追加"参数
<lst name="appends">
<str name="qf">heap_ngrams</str>
</lst>
Run Code Online (Sandbox Code Playgroud)
可惜我无法PositionFilter像 Jayendra Patil 建议的那样使用权利(PositionFilter 使任何查询成为 OR 布尔查询),我使用了不同的方法。
仍然使用EdgeNGramFilter,我添加了这样一个事实:用户输入的每个关键字都是强制性的,并禁用了所有短语。
因此,如果用户要求"cont info",它就会转换为+cont +info. 它比真正的短语更宽松一些,但它成功地做到了我想要的(并且不会仅返回两个术语中的一个结果)。
反对这种解决方法的唯一缺点是术语可以在结果中排列(因此也会找到带有“informatique contrat”的文档),但这并不是什么大问题。
| 归档时间: |
|
| 查看次数: |
10427 次 |
| 最近记录: |