Solr 部分和完整字符串匹配

Posted

技术标签:

【中文标题】Solr 部分和完整字符串匹配【英文标题】:Solr Partial And Full String Match 【发布时间】: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"/>

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

【问题讨论】:

交叉发布:mail-archive.com/solr-user@lucene.apache.org/msg46563.html 【参考方案1】:

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

【讨论】:

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

启用部分单词搜索

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

    NgramFilterFactory 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 的特殊说明

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

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)

【讨论】:

谢谢你,解决了我遇到的一个问题。

以上是关于Solr 部分和完整字符串匹配的主要内容,如果未能解决你的问题,请参考以下文章

选择部分字符串匹配(仅限完整单词)

Solr:准确匹配的得分高于部分匹配

Solr - termfreq部分匹配

正则表达式

re.findall 不返回完整匹配?

solr 名称 关键字两个字段权重设置