使用 Sunspot Solr 搜索 phone 个数字的一部分
Search part of phone number with Sunspot Solr
我正在使用 sunspot Solr 搜索引擎开发 rails 应用程序,我需要在 Solr 4.1 中索引 phone 数字。
比如我有phone号码“+12(456)789-0101”,我的页面应该是通过查询建立的:
- +12 (456) 789-0101(phone 格式正确)
- +12 (456) 789 ....... (phone 的左边部分格式正确)
- .......(456) 789-0101(phone 的右边部分格式正确)
.......(456) 789.......(phone中间部分格式正确)
124567890101(完整 phone 只有数字)
- 1245678..........(phone 的左侧部分带有串联数字)
- ...........890101(phone 的右侧部分带有连接数字)
- ......567890......(phone 的中间部分有连号)
我知道我可以使用:
EdgeNGramFilterFactory
用于将 phone 拆分为 NGram(正面和背面)
WordDelimiterFilterFactory
用于连接数字和拆分 phone 用于零件。
那么,我做了什么:
在 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"/>
将可搜索的 phone 字段定义为“*_phone”类型:
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
运行 重建索引:
bundle exec rake sunspot:rebuild
但是重建索引完成后它不起作用,我只能找到搜索查询的结果:"full phone" 和 "left part of phone"。使用 "middle part of phone" 和 "right part of phone" 搜索没有给我任何结果。
我是不是做错了什么?如何正确地使 phone 部分灼热?
请帮忙。谢谢!
(仅评论Solr部分,不确定SunSpot如何映射)
这里有两点不太对劲:
- side=back 自 Solr 4.4 以来不再是一个选项,因此您可能只是获得相同过滤器的两个副本
- 无论如何,拥有同一个过滤器的两个副本是不好的,因为第二个副本会查看第一个发出的所有令牌,事情会变得一团糟。
这是匹配后缀的好方法,考虑到剥离所有随机非数字内容和 index/query 的不对称性(来自我的 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>
请注意,这对使用默认分析器包含 space 的查询没有帮助,因为它们将在 space 之前 被分解他们进行实地分析。如果您知道您正在搜索 phone 号码,您可以引用搜索字符串或切换到不同的 (probably field) 查询解析器。
如果您确实想要匹配中间部分,也许您不需要任何这些,只需要 NGram,而不是 EdgeNGram 分析。
事实上,这是我的代码,有效:
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"/>
和ruby代码:
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
我正在使用 sunspot Solr 搜索引擎开发 rails 应用程序,我需要在 Solr 4.1 中索引 phone 数字。
比如我有phone号码“+12(456)789-0101”,我的页面应该是通过查询建立的:
- +12 (456) 789-0101(phone 格式正确)
- +12 (456) 789 ....... (phone 的左边部分格式正确)
- .......(456) 789-0101(phone 的右边部分格式正确)
.......(456) 789.......(phone中间部分格式正确)
124567890101(完整 phone 只有数字)
- 1245678..........(phone 的左侧部分带有串联数字)
- ...........890101(phone 的右侧部分带有连接数字)
- ......567890......(phone 的中间部分有连号)
我知道我可以使用:
EdgeNGramFilterFactory
用于将 phone 拆分为 NGram(正面和背面)WordDelimiterFilterFactory
用于连接数字和拆分 phone 用于零件。
那么,我做了什么:
在
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"/>
将可搜索的 phone 字段定义为“*_phone”类型:
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
运行 重建索引:
bundle exec rake sunspot:rebuild
但是重建索引完成后它不起作用,我只能找到搜索查询的结果:"full phone" 和 "left part of phone"。使用 "middle part of phone" 和 "right part of phone" 搜索没有给我任何结果。
我是不是做错了什么?如何正确地使 phone 部分灼热? 请帮忙。谢谢!
(仅评论Solr部分,不确定SunSpot如何映射)
这里有两点不太对劲:
- side=back 自 Solr 4.4 以来不再是一个选项,因此您可能只是获得相同过滤器的两个副本
- 无论如何,拥有同一个过滤器的两个副本是不好的,因为第二个副本会查看第一个发出的所有令牌,事情会变得一团糟。
这是匹配后缀的好方法,考虑到剥离所有随机非数字内容和 index/query 的不对称性(来自我的 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>
请注意,这对使用默认分析器包含 space 的查询没有帮助,因为它们将在 space 之前 被分解他们进行实地分析。如果您知道您正在搜索 phone 号码,您可以引用搜索字符串或切换到不同的 (probably field) 查询解析器。
如果您确实想要匹配中间部分,也许您不需要任何这些,只需要 NGram,而不是 EdgeNGram 分析。
事实上,这是我的代码,有效:
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"/>
和ruby代码:
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