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

PostgreSQL全文搜索:如何拆分无空格连接的数字与单位词汇

PostgreSQL全文搜索:拆分数字与紧连单位为独立词素

要实现to_tsvector('10ml')返回'10':1 'ml':2,同时兼容带空格的格式(如10 ml),可通过以下方案实现:

核心限制说明

默认PostgreSQL文本搜索解析器会将10ml识别为单一的numword类型token,而文本搜索字典仅能修改或替换token,无法拆分token。因此纯通过修改现有配置项无法直接实现,需通过扩展解析器或自定义逻辑完成。

方案1:自定义文本搜索解析器(纯配置扩展)

若希望完全通过修改文本搜索配置实现,需编写C语言扩展创建自定义解析器,定义词法规则将数字与紧连单位拆分为独立token:

  1. 编写C扩展代码,实现词法分析逻辑,识别数字段与单位段并输出独立token。
  2. 编译安装扩展后,将自定义解析器注册到PostgreSQL。
  3. 创建基于该解析器的文本搜索配置,搭配目标字典(如simple或english)。
  4. 使用该配置执行to_tsvector('custom_config', '10ml')即可得到拆分结果。

此方案完全符合配置修改需求,但需要具备PostgreSQL扩展开发能力。

方案2:自定义分词函数(折中实用方案)

若不想编写C扩展,可通过自定义SQL函数实现拆分逻辑,封装后替代默认to_tsvector:

  1. 创建拆分函数,用正则识别并拆分数字+单位组合:
CREATE OR REPLACE FUNCTION split_num_unit(input_text text) RETURNS text[] AS $$
SELECT ARRAY(
  -- 提取数字和单位
  SELECT regexp_replace(match, '^(\d+)([a-zA-Z]+)$', '\1|\2')
  FROM regexp_matches(input_text, '\d+[a-zA-Z]+', 'g') AS matches(match)
  UNION ALL
  -- 保留其他文本内容
  SELECT unnest(regexp_split_to_array(input_text, '\d+[a-zA-Z]+'))
) WHERE input_text ~ '\d+[a-zA-Z]+';
$$ LANGUAGE sql IMMUTABLE;
  1. 创建自定义to_tsvector包装函数:
CREATE OR REPLACE FUNCTION custom_to_tsvector(input_text text) RETURNS tsvector AS $$
SELECT COALESCE(array_to_tsvector(split_num_unit(input_text)), '') || to_tsvector('english', input_text);
$$ LANGUAGE sql IMMUTABLE;
  1. 调用测试:
SELECT custom_to_tsvector('10ml');
-- 返回结果:'10':1 'ml':2
SELECT custom_to_tsvector('10 ml');
-- 返回结果:'10':1 'ml':2

该方案兼顾需求与实现复杂度,可统一处理带空格和无空格的格式。

内容的提问来源于stack exchange,提问作者Viktor Holmberg

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 22:09:51