Postgres 全文本搜索已经足够好了(二)

Tags: postgresql database

上一篇介绍了如何使用postgres进行全文检索,这篇我们将介绍多语言支持以及其他方面内容。

语言支持

Postgres 提供多种语言的内置文本搜索: 丹麦语、 荷兰语、 英语、 芬兰语、 法语、 德语、 匈牙利、 意大利、 挪威、 葡萄牙、 罗马尼亚、 俄罗斯、 西班牙、 瑞典、 土耳其。

SELECT to_tsvector('english', 'We are running');
 to_tsvector
-------------
 'run':3
(1 row)

SELECT to_tsvector('french', 'We are running');
        to_tsvector
----------------------------
 'are':2 'running':3 'we':1
(1 row)

一个列可以用于创建基于我们起始模型的 tsvector。让我们假设post可以用不同语言编写和post包含不同语言。

ALTER TABLE post ADD language text NOT NULL DEFAULT('english');

现在,我们可以重建我们的文档来使用此语言列。

SELECT to_tsvector(post.language::regconfig, post.title) || 
       to_tsvector(post.language::regconfig, post.content) ||
       to_tsvector('simple', author.name) ||
       to_tsvector('simple', coalesce((string_agg(tag.name, ' ')), '')) as document
FROM post
JOIN author ON author.id = post.author_id
JOIN posts_tags ON posts_tags.post_id = posts_tags.tag_id
JOIN tag ON tag.id = posts_tags.tag_id
GROUP BY post.id, author.id;

没有显式强制转换:: regconfig 查询将生成一个错误:

ERROR:  function to_tsvector(text, text) does not exist

regconfig 是表示 Postgres 中的文本搜索配置的对象标识符类型:http://www.postgresql.org/docs/9.3/static/datatype-oid.html

现在将使用基于 post.language 的正确语言构建我们的文档的词汇。
我们还使用simple, 一种Postgres提供的内置搜索文本配置。simple不忽略停止词并且并不试图找到这个词的干。simple模式下由一个空格分隔每个组是一个词 ;simple的文本搜索配置将单词作为实际的数据,如一个人的名字,我们不可能想要寻找词干。

SELECT to_tsvector('simple', 'We are running');
        to_tsvector
----------------------------
 'are':2 'running':3 'we':1
(1 row)

带重音符号的字符

当你建立一个支持多语言的搜索引擎你还会碰到的口音问题。在许多语言中口音是很重要的,并且可以更改这个词的含义。Postgres 提供了unaccent扩展,可以用于unaccentuate 的内容。

CREATE EXTENSION unaccent;
SELECT unaccent('èéêë');

 unaccent
----------
 eeee
(1 row)

让我们向我们的post表添加一些带重音符号的内容。

INSERT INTO post (id, title, content, author_id, language) 
VALUES (4, 'il était une fois', 'il était une fois un hôtel ...', 2,'french')

如果我们想要忽略的口音,在我们建立时可以简单地执行以下操作:

SELECT to_tsvector(post.language, unaccent(post.title)) || 
       to_tsvector(post.language, unaccent(post.content)) ||
       to_tsvector('simple', unaccent(author.name)) ||
       to_tsvector('simple', unaccent(coalesce(string_agg(tag.name, ' '))))
JOIN author ON author.id = post.author_id
JOIN posts_tags ON posts_tags.post_id = posts_tags.tag_id
JOIN tag ON author.id = post.author_id
GROUP BY p.id

这可以工作但有点繁琐而且为了处理错误需要更多的空间。我们也可以为非重音字符的支持生成一个新的文本搜索配置。

CREATE TEXT SEARCH CONFIGURATION fr ( COPY = french );
ALTER TEXT SEARCH CONFIGURATION fr ALTER MAPPING
FOR hword, hword_part, word WITH unaccent, french_stem;

当我们使用这种新的文本搜索配置时,我们可以看到词汇

SELECT to_tsvector('french', 'il était une fois');
 to_tsvector
-------------
 'fois':4
(1 row)

SELECT to_tsvector('fr', 'il était une fois');
    to_tsvector
--------------------
 'etait':2 'fois':4
(1 row)

这可以返回相同的结果,请看下面查询:

SELECT to_tsvector('french', unaccent('il était une fois'));
    to_tsvector
--------------------
 'etait':2 'fois':4
(1 row)

本文链接:http://www.4byte.cn/learning/120046/postgres-quan-wen-ben-sou-suo-yi-jing-zu-gou-hao-liao-er.html