• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • MsSql
  • Mysql
  • oracle
  • MariaDB
  • DB2
  • SQLite
  • PostgreSQL
  • MongoDB
  • Redis
  • Access
  • 数据库其它
  • sybase
  • HBase
您的位置:首页 > 数据库 >数据库其它 > 详细讲解PostgreSQL中的全文搜索的用法

详细讲解PostgreSQL中的全文搜索的用法

作者: 字体:[增加 减小] 来源:互联网 时间:2017-05-11

通过本文主要向大家介绍了postgresql 全文检索,postgresql,postgresql教程,postgresql下载,postgresql官网等相关知识,希望本文的分享对您有所帮助

开发Web应用时,你经常要加上搜索功能。甚至还不知能要搜什么,就在草图上画了一个放大镜。

搜索是项非常重要的功能,所以像elasticsearch和SOLR这样的基于lucene的工具变得很流行。它们都很棒。但使用这些大规模“杀伤性”的搜索武器前,你可能需要来点轻量级的,但又足够好的搜索工具。

所谓“足够好”,我是指一个搜索引擎拥有下列的功能:

  •     词根(Stemming)
  •     排名/提升(Ranking / Boost)
  •     支持多种语言
  •     对拼写错误模糊搜索
  •     方言的支持

幸运的是PostgreSQL对这些功能全支持。


本文的目标读者是:

  •     使用PostgreSQL,同时又不想安装其它的搜索引擎。
  •     使用其它的数据库(比如MySQL),同时需要更好的全文搜索功能。

本文中我们将通过下面的表和数据说明PostgreSQL的全文搜索功能。

 

CREATE TABLE author(
 id SERIAL PRIMARY KEY,
 name TEXT NOT NULL);
CREATE TABLE post(
 id SERIAL PRIMARY KEY,
 title TEXT NOT NULL,
 content TEXT NOT NULL,
 author_id INT NOT NULL references author(id) );
CREATE TABLE tag(
 id SERIAL PRIMARY KEY,
 name TEXT NOT NULL );
CREATE TABLE posts_tags(
 post_id INT NOT NULL references post(id),
 tag_id INT NOT NULL references tag(id)
 );
INSERT INTO author (id, name) 
VALUES (1, 'Pete Graham'), 
  (2, 'Rachid Belaid'), 
  (3, 'Robert Berry');
 
INSERT INTO tag (id, name) 
VALUES (1, 'scifi'), 
  (2, 'politics'), 
  (3, 'science');
 
INSERT INTO post (id, title, content, author_id) 
VALUES (1, 'Endangered species', 'Pandas are an endangered species', 1 ), 
  (2, 'Freedom of Speech', 'Freedom of speech is a necessary right missing in many countries', 2), 
  (3, 'Star Wars vs Star Trek', 'Few words from a big fan', 3);
 
INSERT INTO posts_tags (post_id, tag_id) 
VALUES (1, 3), 
  (2, 2), 
  (3, 1);
</div>

这是一个类博客的应用。它有post表,带有title和content字段。post通过外键关联到author。post自身还有多个标签(tag)。

什么是全文搜索

首先,让我们看一下定义:

    在文本检索中,全文搜索是指从全文数据库中搜索计算机存储的单个或多个文档(document)的技术。全文搜索不同于基于元数据的搜索或根据数据库中原始文本的搜索。

    -- 维基百科

这个定义中引入了文档的概念,这很重要。当你搜索数据时,你在寻找你想要找到的有意义的实体,这些就是你的文档。PostgreSQL的文档中解释地很好。

    文档是全文搜索系统中的搜索单元。比如,一篇杂质文章或是一封邮件消息。

    -- Postgres 文档

这里的文档可以跨多个表,代表为我们想要搜索的逻辑实体。
 
构建我们的文档(document)

上一节,我们介绍了文档的概念。文档与表的模式无关,而是与数据相关,把字段联合为一个有意义的实体。根据示例中的表的模式,我们的文档(document)由这些组成:

  •     post.title
  •     post.content
  •     post的author.name
  •     关联到post的所有tag.name

根据这些要求产生文档,SQL查询应该是这样的:
 
 

SELECT post.title || ' ' || 
  post.content || ' ' ||
  author.name || ' ' ||
  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;
 
    document --------------------------------------------------
 Endangered species Pandas are an endangered species Pete Graham politics
 Freedom of Speech Freedom of speech is a necessary right missing in many countries Rachid Belaid politics
 Star Wars vs Star Trek Few words from a big fan Robert Berry politics
(3 rows)
</div>

由于用post和author分组了,因为有多个tag关联到一个post,我们使用string_agg()作聚合函数。即使author是外键并且一个post不能有多个author,也要求对author添加聚合函数或者把author加到GROUP BY中。

我们还用了coalesce()。当值可以是NULL时,使用coalesce()函数是个很好的办法,否则字符串连接的结果将是NULL。


至此,我们的文档只是一个长string,这没什么用。我们需要用to_tsvector()把它转换为正确的格式。
 

SELECT to_tsvector(post.title) || 
  to_tsvector(post.content) ||
  to_tsvector(author.name) ||
  to_tsvector(coalesce((string_agg(tag.name, ' ')), '')) as documentFROM 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;
    document 
-------------------------------------------------- 
'endang':1,6 'graham':9 'panda':3 'pete':8 'polit':10 'speci':2,7
'belaid':16 'countri':14 'freedom':1,4 'mani':13 'miss':11 'necessari':9 'polit':17 'rachid':15 'right':10 'speech':3,6
'berri':13 'big':10 'fan':11 'polit':14 'robert':12 'star':1,4 'trek':5 'vs':3 'war':2 'word':7
(3 rows)
</div>

这个查询将返回适于全文搜索的tsvector格式的文档。让我们尝试把一个字符串转换为一个tsvector。
 

SELECT to_tsvector('Try not to become a man of success, but rather try to become a man of value');
</div>

这个查询将返回下面的结果:
 

        to_tsvector
----------------------------------------------------------------------
'becom':4,13 'man':6,15 'rather':10 'success':8 'tri':1,11 'valu':17(1 row)
</div>

发生了怪事。首先比原文的词少了,一些词也变了(try变成了tri),而且后面还有数字。怎么回事?

一个tsvector是一个标准词位的有序列表(sorted list),标准词位(distinct lexeme)就是说把同一单词的各种变型体都被标准化相同的。


标准化过程几乎总是把大写字母换成小写的,也经常移除后缀(比如英语中的s,es和ing等)。这样可以搜索同一个字的各种变体,而不是乏味地输入所有可能的变体。

数字表示词位在原始字符串中的位置,比如“man"出现在第6和15的位置上。你可以自己数数看。

Postgres中to_tesvetor的默认配置的文本搜索是“英语“。它会忽略掉英语中的停用词(stopword,译注:也就是am is are a an等单词)。

这解释了为什么tsvetor的结果比原句子中的单词少。后面我们会看到更多的语言和文本搜索配置。

查询

我们知道了如何构建一个文档,但我们的目标是搜索文档。我们对tsvector搜索时可以使用@@操作符,使用说明见此处。看几个查询文档的例子。
 

> select to_tsvector('If you can dream it, you can do it') @@ 'dream';
 ?column?
----------
 t
(1 row)
 
> select to_tsvector('It''s kind of fun to do the impossible') @@ 'impossible';
 
 ?column?
----------
 f
(1 row)
</div>

第二个查询返回了假,因为我们需要构建一个tsquery,使用@@操作符时,把字符串转型(cast)成了tsquery。下面显示了这种l转型和使用to_tsquery()之间的差别。
 

SELECT 'impossible'::tsquery, to_tsquery('impossible');
 tsquery | to_tsquery
--------------+------------
 'impossible' | 'imposs'(1 row)
</div>

但"dream"的词位与它本身相同。
 

SELECT 'dream'::tsquery, to_tsquery('dream');
 tsquery | to_tsquery
--------------+------------
 'dream'  | 'dream'(1 row)
</div>

从现在开始我们使用to_tsquery查询文档。

分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • 详细讲解PostgreSQL中的全文搜索的用法

相关文章

  • 2017-05-11数据库中删除语句Drop、Delete、Truncate的相同点和不同点的比较(实例说明)
  • 2017-05-11带参数的sql和不带参数的sql存储过程区别第1/2页
  • 2017-05-11详细讲解PostgreSQL中的全文搜索的用法
  • 2017-05-11虚拟主机ACCESS转换成MSSQL完全攻略(图文教程)
  • 2017-05-11数据库修改多对多的中间表的记录的技巧
  • 2017-05-11在PostgreSQL上安装并使用扩展模块的教程
  • 2017-05-11sql学习之CASE WHEN THEN ELSE END的用法
  • 2017-05-11SQL嵌套查询总结
  • 2017-05-11修改插入时间不匹配问题
  • 2017-12-08ETL流程概述及常用实现方法

文章分类

  • MsSql
  • Mysql
  • oracle
  • MariaDB
  • DB2
  • SQLite
  • PostgreSQL
  • MongoDB
  • Redis
  • Access
  • 数据库其它
  • sybase
  • HBase

最近更新的内容

    • 本地SQL注射攻略分析曝光
    • Hinted Handoff:在写入路径中修复
    • SQL like子句的另一种实现方法(速度比like快)
    • 大数据量,海量数据处理方法总结
    • SequoiaDB巨杉数据库领跑性能测试,性能超越MongoDB、Cassandra
    • 在PostgreSQL中使用数组时值得注意的一些地方
    • elasticsearch基本参数配置
    • 数据库正规化和设计技巧
    • SQL 注入式攻击的本质
    • 多种获取远程连接access数据库的方法

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有