【问题标题】:Solr - termfreq partial matchesSolr - termfreq 部分匹配
【发布时间】:2015-04-07 01:46:41
【问题描述】:

我正在使用 Solr 查询一组文档,我想获取某个词的匹配数,现在我正在使用

termfreq(text,'manage')

然而这并没有命中ManagerManagement

termfreq(text,'manage*')

返回相同的计数。我试过使用不同的标记器,有些甚至不接受*,而且我还没有找到一个返回正确数量的匹配项。

字段:

<field name="text" type="text_general" indexed="true" stored="true" termVectors="true" termPositions="true" termOffsets="true" required="false"/>

有没有办法让termfreq 也计算部分匹配?

【问题讨论】:

  • 小心你问的问题......“部分匹配”通常不是一个好主意,例如你想让“up”匹配“cup”吗? “提升”? “晚餐”? “库比蒂诺”?一个典型的解决方案是搜索词“stems”(en.wikipedia.org/wiki/Stemming),这是你想要的吗?

标签: search solr match keyword


【解决方案1】:

您需要向分析器添加一些自定义标记器和过滤器类。

在您的 /shared/field_types.xml 文件中,像这样创建一个新类型:

<fieldType name="text" class="solr.TextField" omitNorms="false">
    <analyzer>
      <tokenizer class="solr.StandardTokenizerFactory"/>
      <filter class="solr.StandardFilterFactory"/>
      <filter class="solr.LowerCaseFilterFactory"/>
    </analyzer>
</fieldType>

在 /shared/fields.xml 中:

<field name="text" stored="true" type="text" multiValued="false" indexed="true"/> 
<dynamicField name="*_text" stored="true" type="text" multiValued="false" indexed="true"/>

并将其用作“文本”作为字段的类型。

更高级的解决方案:

 <fieldType name="startsWith" class="solr.TextField" positionIncrementGap="100">
    <analyzer type="index">
      <tokenizer class="solr.KeywordTokenizerFactory"/>
      <filter class="solr.LowerCaseFilterFactory"/>
      <!-- remove words/chars we don't care about -->
      <filter class="solr.PatternReplaceFilterFactory" pattern="[^a-zA-Z0-9 ]" replacement="" replace="all"/>
      <!-- now remove any extra space we have, since spaces WILL influence matching -->
      <filter class="solr.PatternReplaceFilterFactory" pattern="\s+" replacement=" " replace="all"/>
      <filter class="solr.TrimFilterFactory"/>
      <filter class="solr.ASCIIFoldingFilterFactory"/>
      <filter class="solr.EdgeNGramFilterFactory" minGramSize="1" maxGramSize="50"/>
    </analyzer>
    <analyzer type="query">
      <tokenizer class="solr.KeywordTokenizerFactory"/>
      <filter class="solr.LowerCaseFilterFactory"/>
      <filter class="solr.PatternReplaceFilterFactory" pattern="[^a-zA-Z0-9 ]" replacement="" replace="all"/>
      <filter class="solr.PatternReplaceFilterFactory" pattern="\s+" replacement=" " replace="all"/>
      <filter class="solr.TrimFilterFactory"/>
      <filter class="solr.ASCIIFoldingFilterFactory"/>
    </analyzer>
  </fieldType>

在/shared/fields.xml:

<dynamicField name="*_starts_with" stored="true" type="startsWith" multiValued="false" indexed="true"/>

然后,在核心的 schema.xml 的顶层添加:

<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="../../../shared/fields.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="../../../shared/field_types.xml"/>

并将其添加到核心 schema.xml 中的 copyFields:

 <copyFields>
      <copyField source="yourField" dest="yourField_text"/>
      <copyField source="yourField" dest="yourField_starts_with"/>
      ...
 </copyFields>

【讨论】:

  • 这两种方法都会导致 termfreq 返回计数为零,而不是它甚至不计算精确匹配lol
  • 您将哪个字段用于 termfreq、yourField 或 yourField_Text/yourField_starts_with?请注意,这些示例假设您实际上并未将索引字段命名为“文本”。
  • 我完全从高级解决方案中复制了您的代码。我正在使用 yourField(在我的情况下,该字段称为 textRaw)现在它返回完全匹配但它仍然不计算部分匹配。使用 yourField_starts_with 不会产生匹配项
  • 您可能想要使用简单的解决方案。确保您的字段属于“文本”类型
  • 这个简单的解决方案是我一直在使用的,它有效但只计算完全匹配...
【解决方案2】:

我也遇到了同样的问题。我需要计算termfreq,它也应该匹配单词的子部分。 添加这个FieldType就解决了。

<fieldType name="startWith" class="solr.TextField">
  <analyzer type="index">
    <tokenizer class="solr.StandardTokenizerFactory"/>
    <filter class="solr.LowerCaseFilterFactory"/>
    <filter class="solr.EdgeNGramFilterFactory" minGramSize="2" maxGramSize="15" />
  </analyzer>
  <analyzer type="query">
    <tokenizer class="solr.StandardTokenizerFactory"/>
    <filter class="solr.LowerCaseFilterFactory"/>
  </analyzer>
</fieldType>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-12-09
    • 1970-01-01
    • 2011-06-17
    • 1970-01-01
    • 2017-03-02
    • 2015-03-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多