【问题标题】:Solr Partial And Full String MatchSolr 部分和完整字符串匹配
【发布时间】:2011-06-17 00:47:53
【问题描述】:

我正在尝试允许在 Solr 中搜索部分字符串,因此如果有人搜索“ppopota”,他们会得到与搜索“河马”相同的结果。我上下阅读了文档,感觉自己已经用尽了所有选择。到目前为止,我有以下内容:

定义一个新的字段类型:

<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"/>

唉,这行不通。我错过了什么?

【问题讨论】:

标签: search lucene solr


【解决方案1】:

您正在使用EdgeNGramFilterFactory 生成标记“hi”、“hip”、“hipp”等,因此它不会匹配“ppopota”。请改用 NGramFilterFactory。

【讨论】:

  • 很好,但这并没有帮助。我也尝试将 text_ngrams 的内容复制到这样的文本中: 但这也没有效果。
  • @user593282:你重建索引了吗?
  • 是的,我做到了。这里似乎还有别的东西在起作用。
  • @user593282:您是在“text”字段还是“text_ngrams”字段中搜索?
  • 我尝试在两个字段中搜索相同(否定)结果。
【解决方案2】:

启用部分单词搜索

您必须编辑本地 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,否则即使你为你的模型配置了全文搜索,你也会得到需要输入全词的默认行为。

更上一层楼

5 ways to speed up indexing

使用 Heroku 编辑 websolr schema.xml 的特殊说明

  1. 转到您应用的 Heroku 在线仪表板
  2. 转到资源选项卡,然后单击 Websolr 插件
  3. 点击索引下的默认链接
  4. 点击高级配置链接
  5. 从本地粘贴您的 schema.xml,包括您选择的 Ngram 标记器的配置(如上所述)。保存。
  6. 复制“配置您的 Heroku 应用程序”框中的链接,然后将其粘贴到终端中以在您的 heroku 配置中设置您的 WEBSOLR_URL 链接。
  7. 点击“索引状态”链接获取漂亮的统计信息,看看您的运行速度是快还是慢。
  8. 重新索引所有内容

heroku 运行 rake 太阳黑子:reindex[5000]

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

【讨论】:

  • 但是这个问题和 Heroku 有什么关系呢? O_o
  • 好点子,巴巴吉德。我在自己的世界里,每个人的配置都和我一样。编辑答案。
  • 谢谢亚伦。部分 Solr 搜索把我逼疯了。
  • @AaronHenderson 指向“加快索引速度的 5 种方法”的链接已损坏。你有更新的链接吗?
【解决方案3】:

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

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 正在使用 pow 1.0 搜索字段 name_de_partial 和使用 pow 3.0 在 name_de 中搜索

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

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

【讨论】:

    【解决方案4】:

    如果您在索引和查询时都设置 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)

    【讨论】:

    • 谢谢你,解决了我遇到的一个问题。
    猜你喜欢
    • 2015-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-26
    • 2012-06-15
    • 1970-01-01
    相关资源
    最近更新 更多