我在Rails应用程序中使用pg_search gem来搜索用户 - 他们的bios和相关的技能模型。用户是开发人员,因此他们的技能包括“CSS”,“C ++”,“C#”,“Objective C”等等......
我最初使用的是以下搜索范围:
pg_search_scope :search,
against: [:bio],
using: {tsearch: {dictionary: "english", prefix: true}},
associated_against: {user: [:fname, :lname], skills: :name}
但是,如果你在这种情况下搜索“C ++”,你会得到包含“CSS”(其中包括)的结果。我更改了范围以使用“简单”字典并删除了前缀:
pg_search_scope :search_without_prefix,
against: [:bio],
using: {tsearch: {dictionary: "simple"}},
associated_against: {user: [:fname, :lname], skills: :name}
这解决了一些问题 - 例如,搜索“C ++”并不显示“CSS”。但是,搜索“C ++”或“C#”仍然匹配列出“C”或“Objective C”的用户
我绝对可以进行基本ILIKE
匹配,但希望尽可能使用pg_search来完成此任务。
答案 0 :(得分:2)
我会评论,但我还没有足够的声誉。
我一直在研究pg_search
,这使我更深入地了解PostgreSQL全文搜索。它是一个复杂的模块,但它有ts_debug()命令来帮助理解输入字符串的解析方式。测试字符串“C ++ CSS C#Objective C”的ts_debug()输出非常有启发性。看起来“#和”+“在英语的默认配置中被视为空格。我认为您可能必须修改PostgreSQL中的解析器以获得您想要的行为。
postgres=# SELECT * FROM ts_debug('english', 'C++ CSS C# Objective C');
alias | description | token | dictionaries | dictionary | lexemes
-----------+-----------------+-----------+----------------+--------------+----------
asciiword | Word, all ASCII | C | {english_stem} | english_stem | {c}
blank | Space symbols | + | {} | |
blank | Space symbols | + | {} | |
asciiword | Word, all ASCII | CSS | {english_stem} | english_stem | {css}
blank | Space symbols | | {} | |
asciiword | Word, all ASCII | C | {english_stem} | english_stem | {c}
blank | Space symbols | # | {} | |
asciiword | Word, all ASCII | Objective | {english_stem} | english_stem | {object}
blank | Space symbols | | {} | |
asciiword | Word, all ASCII | C | {english_stem} | english_stem | {c}
(10 rows)
BTW,如果您想学习PostgreSQL全文搜索,这是一个非常有用的教程:http://shisaa.jp/postset/postgresql-full-text-search-part-1.html
<强>更新强>
我在PostgreSQL全文搜索中找到了一个解决方案。它涉及使用此处记录的test_parser
扩展名:http://www.postgresql.org/docs/9.1/static/test-parser.html
psql
中需要首先进行一些配置:
postgres=# CREATE EXTENSION test_parser;
postgres=# CREATE TEXT SEARCH CONFIGURATION testcfg ( PARSER = testparser );
postgres=# ALTER TEXT SEARCH CONFIGURATION testcfg
ADD MAPPING FOR word WITH english_stem;
现在,您可以索引测试字符串,并根据需要将“C ++”之类的术语视为单独的标记:
postgres=# SELECT to_tsvector('testcfg', 'C++ CSS C# Objective C #GT40 GT40 added joined');
to_tsvector
----------------------------------------------------------------------------
'#gt40':6 'ad':8 'c':5 'c#':3 'c++':1 'css':2 'gt40':7 'join':9 'object':4
(1 row)
问题仍然是如何将其整合到pg_search
中。我正在看下一个。