使用pg_search匹配特殊字符(例如#,+)

Lev*_*Lev 5 ruby ruby-on-rails pg rails-postgresql pg-search

我在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}
Run Code Online (Sandbox Code Playgroud)

但是,如果在这种情况下搜索"C++",则会得到包含"CSS"(包括其他内容)的结果.我更改了范围以使用"简单"字典并删除了前缀:

pg_search_scope :search_without_prefix,
  against: [:bio],
  using: {tsearch: {dictionary: "simple"}}, 
  associated_against: {user: [:fname, :lname], skills: :name}
Run Code Online (Sandbox Code Playgroud)

这解决了一些问题 - 例如,搜索"C++"并不显示"CSS".但是,搜索"C++"或"C#"仍然匹配列出"C"或"Objective C"的用户

我绝对可以做一个基本的ILIKE匹配,但如果可能的话,希望用pg_search完成这个.

gar*_*999 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)
Run Code Online (Sandbox Code Playgroud)

顺便说一句,如果你想学习 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;
Run Code Online (Sandbox Code Playgroud)

现在,您可以索引一个测试字符串,并根据需要看到像“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)
Run Code Online (Sandbox Code Playgroud)

问题仍然是如何将其集成到pg_search. 我接下来正在看这个。