2012-12-30 27 views
9

我在模型中使用pg_search进行一些文本搜索。在其他属性中,我有一个url字段。使用Rails进行Postgres全文搜索的词分隔符

不幸的是,Postgres似乎没有将/.识别为单词分隔符,因此我无法在url内进行搜索。

示例:在http://test.com中搜索test不会产生任何结果。

有没有办法解决这个问题,也许使用另一个宝石或一些内联SQL?

+0

作为变通,你可以有另一列/使用url属性和公认的字分隔符,并搜索针对代替 – AJcodez

回答

0

我最后修改pg_search宝石支持任意ts_vector表达,而不是单纯的列名。 的变化是here

现在我可以这样写:

pg_search_scope :search, 
    against: [[:title , 'B'], ["to_tsvector(regexp_replace(url, '[^\\w]+', ' ', 'gi'))", 'A']], 
    using: {tsearch: {dictionary: "simple"}} 
5

正如文档中所述(并由AJcodez注意到),有一个解决方案为tsvector索引创建专用列。然后定义映入插入到索引网址正确的触发:

CREATE test_url (url varchar NOT NULL, url_tsvector tsvector NOT NULL); 

此方法将transorm任何非字母字符转换成单一的空间,并转动字符串转换成的tsvector:

CREATE OR REPLACE FUNCTION generate_url_tsvector(varchar) 
RETURNS tsvector 
LANGUAGE sql 
AS $_$ 
    SELECT to_tsvector(regexp_replace($1, '[^\w]+', ' ', 'gi')); 
$_$; 

现在创建一个触发器,它调用此函数:

CREATE OR REPLACE FUNCTION before_insert_test_url() 
RETURNS TRIGGER 
LANGUAGE plpgsql AS $_$ 
BEGIN; 
    NEW.url_tsvector := generate_url_tsvector(NEW.url); 

    RETURN NEW; 
END; 
$_$ 
; 

CREATE TRIGGER before_insert_test_url_trig 
BEFORE INSERT ON test_url 
FOR EACH ROW EXECUTE PROCEDURE before_insert_test_url(); 

现在,当插入url时,url_tsvectorè字段将自动填充。

INSERT INTO test_url (url) VALUES ('http://www.google.fr'); 
TABLE test_url; 

id   url      url_tsvector    

    2 http://www.google.fr 'fr':4 'googl':3 'http':1 'www':2 

(1 row) 

要在URL上进行FT搜索,您只需要根据此字段进行查询。

SELECT * FROM test_url WHERE url_tsvector @@ 'google'::tsquery; 
+1

你不如果您使用[功能索引](http://www.postgresql.org/docs/8.4/static/indexes-expressional.html),甚至需要额外的列。此外,您可以创建一个[view](http://www.postgresql.org/docs/8.4/static/tutorial-views.html),以避免需要指定用于创建索引的表达式的完整形式执行查询。 –

+0

正如你所建议的那样,我破解了这个gem来支持任意的ts_vector调用,这将允许我使用'regexp_replace'。 使用插入/更新触发器可能会带来性能上的好处,但我觉得这个解决方案对我的需求来说太麻烦了。 感谢您的帮助。 – mihai