当前位置: 首页>>技术问答>>正文


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>

定义类型为”testedgengrams”的字段:

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

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

<copyField source="text_ngrams" dest="text"/>

唉,那不行。我失踪了什么

最佳解决办法

您正在使用生成令牌’hi’,’hip’,’hipp’等的EdgeNGramFilterFactory,因此不符合’ppopota’。改用NGramFilterFactory。

次佳解决办法

启用部分词搜索

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

  1. NGramFilterFactory

  2. EdgeNGramFilterFactory

这是我的样子:sample solr schema.xml

这是要粘贴的行:

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

EdgeNGram

我用了EdgeN选项。它不允许在单词的中间进行搜索,但它允许从单词开头开始部分单词搜索。这可以减少你不想要的假阳性/比赛,表现更好,通常不会被用户错过。另外,我喜欢minGramSize = 2,所以你必须输入至少2个字符。有些人把它设为3。

一旦您的本地设置和工作,您必须编辑websolr使用的schema.xml,否则您将获得默认行为,即使您为模型配置了全文搜索,也需要输入full-word。

把它带到一个新的水平

5 ways to speed up indexing

如果您使用Heroku,则需要编辑websolr schema.xml的特殊说明

  1. 转到您的应用程序的Heroku在线信息中心

  2. 转到资源选项卡,然后单击Websolr add-on

  3. 单击索引下的默认链接

  4. 单击高级配置链接

  5. 从你的本地贴上你的schema.xml,包括你所选择的Ngram标记器的配置(上面提到的)。保存。

  6. 复制“配置您的Heroku应用程序”框中的链接,然后将其粘贴到终端中,将您的WEBSOLR_URL链接设置为您的heroku配置。

  7. 单击索引状态链接以获取漂亮的统计信息,看看您是快速还是慢速运行。

  8. Reindex一切

heroku run rake sunspot:reindex[5000]

  • 不要使用英雄运行耙子太阳黑子:solr:reindex – 它已被弃用,不接受任何参数,而是更慢

  • 默认批量大小为50,大多数人建议使用1000,但我看到明显更快的结果(每秒1000行,而不是大约500 rps),最多可以达到5000+

第三种解决办法

好,我正在做同样的事情与字段名称

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在pow1中搜索field_de_partial的字段,在pow_3中使用name_de进行搜索

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

而字段name_de_partial正在使用特定的solr过滤器,因此可以使用查询”hip”或”ppie”或”ippi”找不到字母”hippie”。

第四种办法

如果您在索引和查询时间设置了EdgeNGramFilterFactory或NGramFilterFactory,结合q.op = AND(或者如果使用dismax则默认为= 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)

参考文献

注:本文内容整合自google/baidu/bing辅助翻译的英文资料结果。如果您对结果不满意,可以加入我们改善翻译效果:gxnotes#qq.com(#替换为@)。

本文由《共享笔记》整理, 博文地址: https://gxnotes.com/article/192137.html,未经允许,请勿转载。
Go