Solr部分和全字符串匹配

时间:2011-01-28 04:50:57

标签: search lucene solr

我试图允许搜索Solr中的部分字符串,所以如果有人搜索“ppopota”,他们会得到与搜索“hippopotamus”相同的结果。我上下阅读文档,觉得我已经筋疲力尽了。到目前为止,我有以下内容:

定义新字段类型:

<fieldtype name="testedgengrams" class="solr.TextField">
   <analyzer>
     <tokenizer class="solr.LowerCaseTokenizerFactory"/>
     <filter class="solr.EdgeNGramFilterFactory" minGramSize="2" maxGramSize="15" side="front"/>
  </analyzer>
</fieldtype>

定义“testsgengrams”类型的字段:

<field name="text_ngrams" type="testedgengrams" indexed="true" stored="false"/>

将text_ngrams的内容复制到文本中:

<copyField source="text_ngrams" dest="text"/>
唉,这不起作用。我错过了什么?

4 个答案:

答案 0 :(得分:17)

你正在使用EdgeNGramFilterFactory生成代币'hi','hip','hipp'等,因此它与'ppopota'不匹配。改为使用NGramFilterFactory。

答案 1 :(得分:11)

启用部分字词搜索

您必须编辑本地schema.xml文件(通常在solr / config下)以添加:

  1. NGramFilterFactory
  2. EdgeNGramFilterFactory
  3. 以下是我的看法:sample solr schema.xml

    以下是要粘贴的行:

    <filter class="solr.EdgeNGramFilterFactory" minGramSize="2" maxGramSize="15" side="front"/>
    

    <强> EdgeNGram

    我选择了EdgeN选项。它不允许在单词的中间进行搜索,但它允许从单词的开头开始进行部分单词搜索。这减少了你不想要的误报/匹配,表现更好,并且通常不会被用户遗漏。另外,我喜欢minGramSize = 2,所以你必须输入至少2个字符。有些人将此设置为3。

    设置并运行本地后,必须编辑websolr使用的schema.xml,否则即使您为模型配置了全文搜索,也会获得默认行为,即需要输入全字。

    将其提升到新的水平

    5 ways to speed up indexing

    如果您使用Heroku

    ,则编辑websolr schema.xml的特殊说明
    1. 转到适用于您应用的Heroku在线信息中心
    2. 转到资源选项卡,然后单击Websolr附加组件
    3. 点击索引
    4. 下的默认链接
    5. 单击“高级配置”链接
    6. 从本地粘贴到schema.xml中,包括您选择的Ngram tokenizer的配置(如上所述)。保存。
    7. 复制“配置Heroku应用程序”框中的链接,然后将其粘贴到终端以在heroku配置中设置WEBSOLR_URL链接。
    8. 单击“索引状态”链接以获取漂亮的统计信息,并查看您是快速还是慢速运行。
    9. 重新索引所有内容
    10.   

      heroku run rake sunspot:reindex [5000]

      • 不要使用heroku run rake sunspot:solr:reindex - 不推荐使用,不接受任何参数且速度慢
      • 默认批量大小为50,大多数人建议使用1000,但我已经看到明显更快的结果(每秒1000行而不是大约500 rps)通过将其提高到5000 +

答案 2 :(得分:9)

好的我用字段名称

做同样的事情
name_de

我设法使用像这样的copyField来使用这个东西:

schema.xml中

<schema name="solr-magento" version="1.2">
    <types>
       ...
        <fieldType name="type_name_de_partial" class="solr.TextField">
            <analyzer type="index">
                <tokenizer class="solr.WhitespaceTokenizerFactory"/>
                <filter class="solr.NGramFilterFactory" minGramSize="3" maxGramSize="1000" side="front" />
                <filter class="solr.NGramFilterFactory" minGramSize="3" maxGramSize="1000" side="back" />
                <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" enablePositionIncrements="true"/>
                <filter class="solr.LowerCaseFilterFactory"/>
                <filter class="solr.TrimFilterFactory" />
                <filter class="solr.RemoveDuplicatesTokenFilterFactory"/>
                <filter class="solr.SnowballPorterFilterFactory" language="German" protected="protwords_de.txt"/>
            </analyzer>
            <analyzer type="query">
                <tokenizer class="solr.StandardTokenizerFactory"/>
                <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="0" catenateNumbers="0" catenateAll="0" splitOnCaseChange="1"/>
                <filter class="solr.LowerCaseFilterFactory"/>
                <filter class="solr.TrimFilterFactory" />
                <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
                <filter class="solr.SnowballPorterFilterFactory" language="German" protected="protwords_de.txt"/>
            </analyzer>
        </fieldType>
    </types>

    ...

    <fields>
        ...
        <field name="name_de_partial" type="type_name_de_partial" indexed="true" stored="true"/>
    </fields>

    ....

    <copyField source="name_de" dest="name_de_partial" />
</schema>

然后在solrconfig.xml中创建搜索条件

<requestHandler name="magento_de" class="solr.SearchHandler">
    <lst name="defaults">
        <str name="defType">dismax</str>
        <str name="echoParams">explicit</str>
        <str name="tie">0.01</str>                                          <!-- Tie breaker -->
        <str name="qf">name_de_partial^1.0 name_de^3.0</str>                <!-- Phrase Fields -->
        <str name="pf">name_de_partial^1.0 name_de^3.0</str>                <!-- Phrase Fields -->
        <str name="mm">3&lt;90%</str>                                       <!-- Minimum 'Should' Match [id 1..3 must much all, else 90proc] -->
        <int name="ps">100</int>                                            <!-- Phrase Slop -->
        <str name="q.alt">*:*</str>
        ..
    </lst>
    <arr name="last-components">
        <str>spellcheck</str>
    </arr>
</requestHandler>

使用此solr在字段name_de_partial中搜索pow 1.0,在name_de中搜索pow 3.0

因此,如果引擎在name_de中找到特定的查询字,那么它将被放在列表的顶部。 如果他也在name_de_partial中找到了某些东西,那么它也会被计算并被放入结果中。

并且字段name_de_partial正在使用特定的solr过滤器,因此它可以使用查询“hip”或“ppie”或“ippi”找到单词“hippie”而无需swet。

答案 3 :(得分:5)

如果您在索引和查询时设置了EdgeNGramFilterFactory或NGramFilterFactory,并结合q.op = AND(如果您使用dismax,则默认mm = 100%),您将遇到一些问题。

尝试仅在索引时定义NGramFilterFactory:

<fieldType name="testedgengrams" class="solr.TextField">
    <analyzer type="index">
        <tokenizer class="solr.LowerCaseTokenizerFactory"/>
        <filter class="solr.NGramFilterFactory" minGramSize="3" maxGramSize="15"/>
    </analyzer>
    <analyzer type="query">
        <tokenizer class="solr.LowerCaseTokenizerFactory"/>
    </analyzer>
</fieldType>

或尝试设置q.op = OR(如果使用dismax,则mm = 1)