# 4. 全文检索系统之 pg\_search 实现
#### 1. 前言1
[pg\_search](https://github.com/Casecommons/pg_search)是一个用于**PostgreSQL**全文检索的gem,它使用起来简单,功能也很强大。
以本站为例,文章都是放在articles这张表中,文章有标题和内容,即title和body,现在要对这两个做全文检索。
#### 2. 安装和使用
安装gem
```
gem 'pg_search'
```
查看**pg\_search**的readme文档就可以知道。它主要有两种使用方式,分别是Multi-search和search scopes。Multi-search是适合于网站比较复杂,例如多张表,要把多张表揉在一起,放到一张表来做查找。现在我们的网站简单,不需要这个功能,所以我们来看看search scopes的用法。
```
class Article < ActiveRecord::Base
include PgSearch
pg_search_scope :search_by_title_or_body, :against => [:title, :body]
end
```
用`rails console`创建一些文档,之后就能用`Article.search_by_title_or_body`来搜索了。
这样再结合表单就能实现一个搜索系统的。
#### 3. 其他功能
**pg\_search**还有其他强大的功能。我们来介绍一下。
##### 3.1 关联(Searching through associations)
我们现在是在articles这张上做查询,那是因为我们的网站简单,但有时候是要跨表的,那也很简单。比如,article是has\_many :tags的,就可以这样。
```
class Article < ActiveRecord::Base
include PgSearch
pg_search_scope :search_by_title_or_body,
:against => [:title, :body],
:associated_against => {
:tags => [:name],
}
end
```
可以查看log看具体做了什么操作。其实就是joins之类。
##### 3.2 字典和中文支持(dictionary)
这篇文章[PostgreSQL的全文检索系统之中文支持(三)](http://www.rails365.net/articles/postgresql-de-quan-wen-jian-suo-xi-tong-zhi-zhong-wen-zhi-chi-san)有介绍**PostgreSQL**中文支持。
安装好那个中文插件,和pg\_search结合那太简单了,指定**dictionary**就好了。
```
class Article < ActiveRecord::Base
include PgSearch
pg_search_scope :search_by_title_or_body,
:against => [:title, :body],
:associated_against => {
:tags => [:name],
},
:using => {
:tsearch => {:dictionary => "testzhcfg"}
}
end
```
##### 3.3 权重(Weighting)
可以给需要搜索的项加上优先级,比如,标题要优先于内容。
```
class Article < ActiveRecord::Base
include PgSearch
pg_search_scope :search_by_title_or_body,
:against => {
:title => 'A',
:body => 'B'
},
:associated_against => {
:tags => [:name],
},
:using => {
:tsearch => {:dictionary => "testzhcfg"}
}
end
```
可以看看日志,如果有类似于"setweight"的输出,说明成功了。
##### 3.4 前缀(prefix)
假如要搜索一个词,例如rails,但是忘了怎么拼写,只记得前两个单词,那就是ra,但输入ra时也能找到关于rails的文章,这就是前缀的作用。使用也很简单。
```
class Article < ActiveRecord::Base
include PgSearch
pg_search_scope :search_by_title_or_body,
:against => {
:title => 'A',
:body => 'B'
},
:associated_against => {
:tags => [:name],
},
:using => {
:tsearch => {:dictionary => "testzhcfg", :prefix => true}
}
end
```
##### 3.5 否定(negation)
否定就是可以搜索不包含的内容,比如!ruby,就是不搜索ruby,其他的都搜索,一个相反过程啦。
```
class Article < ActiveRecord::Base
include PgSearch
pg_search_scope :search_by_title_or_body,
:against => {
:title => 'A',
:body => 'B'
},
:associated_against => {
:tags => [:name],
},
:using => {
:tsearch => {:dictionary => "testzhcfg", :prefix => true, :negation => true}
}
```
还有其他各种用法,normalization用于排序,any\_word是否匹配任何一个,dmetaphone模糊匹配等。
完结。