带有连字符和数字的 Postgres 全文搜索

sil*_*rry 2 postgresql full-text-search

我观察到在我看来 Postgres 的 to_tsvector 函数的奇怪行为。

SELECT to_tsvector('english', 'abc-xyz');
Run Code Online (Sandbox Code Playgroud)

返回

'abc':2 'abc-xyz':1 'xyz':3
Run Code Online (Sandbox Code Playgroud)

然而,

SELECT to_tsvector('english', 'abc-001');
Run Code Online (Sandbox Code Playgroud)

返回

'-001':2 'abc':1
Run Code Online (Sandbox Code Playgroud)

为什么不是这样的?

'abc':2 'abc-001':1 '001':3
Run Code Online (Sandbox Code Playgroud)

我应该怎么做才能仅通过数字部分进行搜索,而无需连字符?

Erw*_*ter 8

似乎文本搜索解析器将连字符后跟数字标识为有符号整数符号。调试ts_debug()

SELECT * FROM ts_debug('english', 'abc-001');

   alias   |   description   | token | dictionaries | dictionary | lexemes 
-----------+-----------------+-------+--------------+------------+---------
 asciiword | Word, all ASCII | abc   | {simple}     | simple     | {abc}
 int       | Signed integer  | -001  | {simple}     | simple     | {-001}
Run Code Online (Sandbox Code Playgroud)

其他文本搜索配置(如“简单”而不是“英语”)将无济于事,因为解析器本身在这里“有问题”(有争议)。

解决它的一个简单方法(除了修改解析器,我从未尝试过)是预处理字符串并将连字符替换为 m-dash ( ) 或只是空格以确保它们被标识为"Space symbols"。(实际有符号整数在此过程中会丢失负号。)

SELECT to_tsvector('english', translate('abc-001', '-', '—'))
    @@ to_tsquery ('english', '001');  -- true now
Run Code Online (Sandbox Code Playgroud)

db<>在这里摆弄

  • 谢谢!调用“translate”对我不起作用,因为它不适用于此处未提及的其他用例,但这会: WHERE to_tsvector('english', field)) @@ to_tsquery ('english', '001' ) 或 to_tsvector('english', field)) @@ to_tsquery ('english', '-001'); (2认同)

Vse*_*nov 3

这可以通过 PG13 的 dict-int 插件absval选项来规避。请参阅官方文档

但如果您坚持使用早期的 PG 版本,这里是查询中“数字或负数”解决方法的通用版本。

select regexp_replace($$'test' & '1':* & '2'$$::tsquery::text,
            '''([.\d]+''(:\*)?)', '(''\1 | ''-\1)', 'g')::tsquery;
Run Code Online (Sandbox Code Playgroud)

这导致:

'test' & ( '1':* | '-1':* ) & ( '2' | '-2' )
Run Code Online (Sandbox Code Playgroud)

它将看起来像正数的词素替换为“数字或负数”类型的子查询。
双重强制转换::tsquery::text只是为了展示如何将 tsquery 强制转换为文本。
请注意,它也处理前缀匹配的数字词位。