使用Sunspot Solr搜索部分电话号码

时间:2015-01-25 12:02:50

标签: solr sunspot solr4 sunspot-rails sunspot-solr

我正在使用太阳黑子Solr搜索引擎开发rails app,我需要在Solr 4.1中索引电话号码。

例如,如果我有电话号码" +12(456)789-0101",我的页面应该由查询建立:

  • +12(456)789-0101(电话格式正确)
  • +12(456)789 .........(电话的左侧部分格式正确)
  • .......(456)789-0101(电话的正确部分格式正确)
  • .......(456)789 .........(手机中间部分格式正确)

  • 124567890101(仅限数字的完整手机)

  • 1245678 ..........(带有链接号码的电话的左侧部分)
  • ............ 890101(带有链接号码的电话的右侧部分)
  • ...... 567890 ......(带有数字的电话的中间部分)

我知道我可以使用:

  • EdgeNGramFilterFactory用于将手机分成NGrams(正面和背面)
  • WordDelimiterFilterFactory用于连接数字和拆分部分电话。

所以,我做了什么:

  1. shema.xml中创建新的Solr字段类型:

    <fieldType name="phone_number" class="solr.TextField"> <analyzer type="index"> <tokenizer class="solr.StandardTokenizerFactory"/> <filter class="solr.EdgeNGramFilterFactory" minGramSize="3" maxGramSize="20" side="front"/> <filter class="solr.EdgeNGramFilterFactory" minGramSize="3" maxGramSize="20" side="back"/> </analyzer> </fieldType>

    <dynamicField name="*_phone" stored="false" type="phone_number" multiValued="true" indexed="true"/>

  2. 将可搜索的手机字段定义为&#39; * _ phone&#39;类型:

    string :work_phone, :as => :work_phone, :stored => true do work_phone.gsub(/\D/, '') if work_phone end

    string :mobile_phone, :as => :mobile_phone, :stored => true do mobile_phone.gsub(/\D/, '') if mobile_phone end

  3. 运行重建索引:

    bundle exec rake sunspot:rebuild

    但是当重建索引完成时它不起作用,我可以找到只搜索查询的结果:&#34;完整的手机&#34;和&#34;留下电话&#34;的一部分。使用&#34;手机的中间部分&#34;和#34;电话的正确部分&#34;没有给我任何结果。

  4. 我做错了吗?如何使手机部件正确烧焦? 请帮忙。谢谢!

2 个答案:

答案 0 :(得分:2)

(仅评论Solr部分,不确定SunSpot如何映射它)

这里有一些不太正确的事情:

    自从Solr 4.4起,
  1. side = back 不再是一个选项,所以你可能只是得到了同一个过滤器的两个副本
  2. 无论如何,拥有相同过滤器的两个副本是不好的,因为第二个将查看第一个发出的所有令牌,事情会变得混乱。
  3. 这是匹配后缀的好方法,考虑到剥离所有随机非数字内容和索引/查询的不对称性(来自我的AirPair Solr tutorial):

    <fieldType name="phone" class="solr.TextField">
      <analyzer type="index">
        <tokenizer class="solr.KeywordTokenizerFactory" />
        <filter class="solr.PatternReplaceFilterFactory" pattern="([^0-9])" replacement="" replace="all"/>
        <filter class="solr.ReverseStringFilterFactory"/>
        <filter class="solr.EdgeNGramFilterFactory" minGramSize="3" maxGramSize="30"/>
      </analyzer>
      <analyzer type="query">
        <tokenizer class="solr.KeywordTokenizerFactory" />
        <filter class="solr.PatternReplaceFilterFactory" pattern="([^0-9])" replacement="" replace="all"/>
        <filter class="solr.ReverseStringFilterFactory"/>
      </analyzer>
    </fieldType>
    

    请注意,这对使用默认分析器在其中包含空格的查询没有帮助,因为它们将在 之前在空间上进行分析。如果您知道正在搜索电话号码,则可以引用搜索字符串或切换到其他(probably field)查询解析器。

    如果你想要匹配中间,也许你不想要任何这些,只想要NGram,而不是EdgeNGram分析。

答案 1 :(得分:2)

Ectualy,这是我的代码,有效:

Schema.xml的:

    <fieldType class="solr.TextField" name="phone_number" positionIncrementGap="100">       
    <analyzer type="index">         
      <tokenizer class="solr.WhitespaceTokenizerFactory"/>         
      <filter class="solr.LowerCaseFilterFactory"/>         
      <filter class="solr.NGramFilterFactory" minGramSize="3" maxGramSize="20"/>
    </analyzer>       
    <analyzer type="query">         
      <tokenizer class="solr.WhitespaceTokenizerFactory"/>         
      <filter class="solr.LowerCaseFilterFactory"/>         
      <filter class="solr.WordDelimiterFilterFactory" catenateNumbers="1"/>       
    </analyzer>     
    </fieldType>

 <dynamicField name="*_phone"  stored="false"  type="phone_number" multiValued="false" indexed="true"/>
 <dynamicField name="*_phones" stored="false"  type="phone_number" multiValued="false" indexed="true"/>

红宝石代码:

  text :work_phone

  text :work_phone_parts, :as => :work_phone do
    "00#{work_phone.gsub(/\D/, '')}" if work_phone
  end

  text :mobile_phone

  text :mobile_phone_parts, :as => :mobile_phone do
    "00#{mobile_phone.gsub(/\D/, '')}" if mobile_phone
  end