Postgresql 在简单模式下,在某些设置中丢弃非英语
在一些pg安装中,我注意到以下情况Postgresql 在简单模式下,在某些设置中丢弃非英语,postgresql,full-text-search,Postgresql,Full Text Search,在一些pg安装中,我注意到以下情况 sam=# select '你好 世界'::tsvector; tsvector --------------- '世界' '你好' (1 row) sam=# select to_tsvector('simple', '你好 世界'); to_tsvector ------------- (1 row) 即使我的数据库是这样配置的: MBA:bin sam$ ./psql -l
sam=# select '你好 世界'::tsvector;
tsvector
---------------
'世界' '你好'
(1 row)
sam=# select to_tsvector('simple', '你好 世界');
to_tsvector
-------------
(1 row)
即使我的数据库是这样配置的:
MBA:bin sam$ ./psql -l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
-----------+-------+----------+-------------+-------------+-------------------
postgres | sam | UTF8 | en_AU.UTF-8 | en_AU.UTF-8 |
sam | sam | UTF8 | en_AU.UTF-8 | en_AU.UTF-8 |
template0 | sam | UTF8 | en_AU.UTF-8 | en_AU.UTF-8 | =c/sam +
| | | | | sam=CTc/sam
template1 | sam | UTF8 | en_AU.UTF-8 | en_AU.UTF-8 | =c/sam +
| | | | | sam=CTc/sam
(4 rows)
在其他类似的设置中,我看到选择to_tsvector('simple','你好 世界');代码>正确返回令牌
我如何诊断这个简单的标记器来找出它为什么要丢弃这些字母
最简单的复制似乎是通过postgres应用程序安装postgres。在ubuntu上安装带有区域设置的postgres时不会发生这种情况。不幸的是,文本搜索使用的默认解析器高度依赖于数据库初始化,尤其是lc\u-collate
和当前数据库对象编码
这是由于默认文本解析器的某些内部工作造成的。它大致是:
注意:解析器的“字母”概念由数据库的区域设置决定,特别是lc_ctype
。只包含基本ASCII字母的单词作为单独的标记类型报告,因为有时区分它们很有用
重要的部分是PostgreSQL中的以下注释:
及以下:
/*
* any non-ascii symbol with multibyte encoding with C-locale is
* an alpha character
*/
因此,如果您想使用默认的中文解析器,请确保您的数据库是用C语言环境初始化的,并且您有多字节编码,因此U+007F以上的所有字符都将被视为alpha(包括表意空间U+3000之类的空格!)。通常,以下initdb
调用将执行您期望的操作:
initdb --locale=C -E UTF-8
否则,将跳过汉字并将其视为空白
您可以使用调试功能ts_debug
对此进行检查。使用lc_collate=en_US.UTF-8
初始化的数据库或任何其他标记化失败的配置,您将获得:
SELECT * FROM ts_debug('simple', '你好 世界');
alias | description | token | dictionaries | dictionary | lexemes
-------+---------------+-----------+--------------+------------+---------
blank | Space symbols | 你好 世界 | {} | |
相反,使用lc\u collate=C
和UTF-8数据库(如上所述初始化),您将得到正确的结果:
SELECT * FROM ts_debug('simple', '你好 世界');
alias | description | token | dictionaries | dictionary | lexemes
-------+-------------------+-------+--------------+------------+---------
word | Word, all letters | 你好 | {simple} | simple | {你好}
blank | Space symbols | | {} | |
word | Word, all letters | 世界 | {simple} | simple | {世界}
然而,您的意思似乎是在单词已被规则空格分隔的情况下对中文文本进行标记化,即标记化/分段不会在PostgreSQL中发生。对于这种情况,我强烈建议使用自定义解析器。如果您不使用PostgreSQL简单解析器的其他功能,例如作为标记化URL
对空格字符进行语法分析器标记非常容易实现。事实上,在中,有一个示例代码正是这样做的。该语法分析器将在任何语言环境下工作。该语法分析器中存在缓冲区溢出错误,该错误在2012年得到修复,请确保使用最新版本。请显示工作和非工作设置的PostgreSQL版本。<代码> >选择版本()/<代码>。操作系统也很好。同时,确保你正在比较相同的东西——在一些测试中,你中间有一个空格,有些不是。@ Curigriger-I不知道从哪里开始,我如何诊断什么令牌“简单”?考虑什么不考虑什么。必须有一些表可以解释简单标记器是如何工作的。语法分析器/标记器对于“simple”和其他语言是一样的。这是字典配置;它控制词干和停止词。语法分析器/标记器是用C写的,在PostgreSQL源代码中。现在,请重新阅读我的上一篇文章ous注释-您确实需要检查并查看工作和非工作设置是否有不同之处,从PostgreSQL版本开始。我可以用完全相同的版本来重现这一点,不同之处在于在一种情况下,initdb在任何地方都不会触发区域设置。您能否显示不同的列表(psql-l
)对于这两个案例?你只显示了一半的图片。哇,这真是一团糟。看起来文本搜索引擎真的需要那些精通这些语言的人的爱。谢谢你的广泛回答,这对我有很大帮助。
SELECT * FROM ts_debug('simple', '你好 世界');
alias | description | token | dictionaries | dictionary | lexemes
-------+-------------------+-------+--------------+------------+---------
word | Word, all letters | 你好 | {simple} | simple | {你好}
blank | Space symbols | | {} | |
word | Word, all letters | 世界 | {simple} | simple | {世界}