You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Solr中实现电话号码类同义词的过滤与分词?

问题描述

我需要Solr支持搜索存储格式为+79876543210的电话号码,同时兼容以下多种查询格式:

+79876543210
 79876543210
 89876543210  <-- '+7'替换为地区码'8'
  9876543210  <-- 完全移除'+7'

固定电话场景同样需要兼容多种变体:

+78662123456  <-- '+78662'为特定地区码
 78662123456
 88662123456
  8662123456
      123456  <-- 完全移除地区码

之前试过单独存储号码变体用于搜索,但高亮时会返回<em>123456</em>,而实际展示给用户的是原始号码+78662123456,体验很差。想用managed synonyms但官方文档明确说:

通过REST API对托管资源所做的更改,需重载Solr集合(单服务器模式下为core)后才会应用到活动组件。

每次加数据都重载core不现实,还会有同步问题,求其他Solr原生解决方案。

解决方案

核心思路是用Solr的字符/令牌过滤器,在索引和查询阶段自动将所有号码变体转换成统一的匹配规则,同时保留原始号码用于展示和高亮,全程不需要维护额外同义词或重载core。

1. 定义专用电话号码字段类型

在managed-schema(或旧版schema.xml)中添加针对电话号码的字段类型,通过分析器处理所有变体:

<fieldType name="phone_number" class="solr.TextField" positionIncrementGap="100">
  <!-- 索引阶段:生成所有可能的匹配令牌 -->
  <analyzer type="index">
    <!-- 第一步:移除所有非数字字符,只保留纯数字 -->
    <charFilter class="solr.PatternReplaceCharFilterFactory" 
               pattern="[^0-9]" replacement=""/>
    <!-- 把整个号码作为单个令牌 -->
    <tokenizer class="solr.KeywordTokenizerFactory"/>
    <!-- 生成令牌1:替换开头的7为8(匹配用户输入8开头的号码) -->
    <filter class="solr.PatternReplaceTokenFilterFactory" 
            pattern="^7" replacement="8" preserveOriginal="true"/>
    <!-- 生成令牌2:去掉开头的7(匹配用户输入不带国家码的号码) -->
    <filter class="solr.PatternReplaceTokenFilterFactory" 
            pattern="^7" replacement="" preserveOriginal="true"/>
    <!-- 生成令牌3:提取最后6位数字(匹配用户输入仅本地号码的场景) -->
    <filter class="solr.PatternReplaceTokenFilterFactory" 
            pattern=".*(\d{6})$" replacement="$1" preserveOriginal="false"/>
  </analyzer>
  <!-- 查询阶段:将用户输入转换成可匹配的令牌 -->
  <analyzer type="query">
    <!-- 同样先移除非数字字符 -->
    <charFilter class="solr.PatternReplaceCharFilterFactory" 
               pattern="[^0-9]" replacement=""/>
    <tokenizer class="solr.KeywordTokenizerFactory"/>
    <!-- 把输入的8开头号码转换成7开头,同时保留原始8开头令牌 -->
    <filter class="solr.PatternReplaceTokenFilterFactory" 
            pattern="^8" replacement="7" preserveOriginal="true"/>
  </analyzer>
</fieldType>

分析器逻辑说明

  • 索引时:原始号码+79876543210会被转换成3个令牌:79876543210、89876543210、9876543210;固定电话+78662123456会生成78662123456、88662123456、8662123456、123456。
  • 查询时:用户输入的任何格式都会被转换成对应令牌,比如输入123456直接匹配索引时的最后6位令牌,输入89876543210会生成89876543210和79876543210两个令牌,同时匹配索引中的对应项。

2. 配置字段

添加一个字段,同时存储原始号码并应用上面的分析器:

<field name="phone" type="phone_number" stored="true" indexed="true"/>
  • stored="true":保留原始号码用于展示和高亮
  • indexed="true":用上面的分析器生成索引令牌

3. 高亮配置

查询时只需开启高亮并指定phone字段即可:

hl=true&hl.fl=phone&hl.usePhraseHighlighter=true

因为字段存储的是原始号码,Solr会自动在原始号码上高亮匹配的部分,比如用户搜索123456,返回的高亮结果会正确指向原始号码的对应片段。

额外优化

如果需要区分手机号和固定电话的规则,可以定义两个不同的字段类型,分别调整过滤器的正则规则(比如手机号保留最后10位,固定电话保留最后6位)。


内容的提问来源于stack exchange,提问作者Kasbolat Kumakhov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 11:05:21