2013-10-15 13 views
5

Ich verwende das Juwel pg_search in einer Rails-App, um nach Benutzern zu suchen - nach ihrem Bios und dem zugehörigen Skill-Modell. Benutzer sind Entwickler, so dass ihre Fähigkeiten Dinge wie "CSS" schließen "C++", "C#", "Objective C", etc ...Übereinstimmende Sonderzeichen (z. B. #, +) mit pg_search

ich zunächst das den folgenden Suchbereich verwendet wurde:

pg_search_scope :search, 
    against: [:bio], 
    using: {tsearch: {dictionary: "english", prefix: true}}, 
    associated_against: {user: [:fname, :lname], skills: :name} 

Wenn Sie jedoch in diesem Fall "C++" suchen, erhalten Sie unter anderem Ergebnisse, die "CSS" enthalten. Ich änderte den Umfang den „einfachen“ Wörterbuch zu verwenden und prefixing entfernt:

pg_search_scope :search_without_prefix, 
    against: [:bio], 
    using: {tsearch: {dictionary: "simple"}}, 
    associated_against: {user: [:fname, :lname], skills: :name} 

Diese festen einige Dinge - zum Beispiel der Suche „C++“ nicht „CSS“. Aber, Suche "C++" oder "C#" entspricht immer noch Benutzer, die "C" oder "Objective C" aufgeführt haben

Ich kann auf jeden Fall eine grundlegende ILIKE übereinstimmen, aber hoffe, dies mit pg_search zu erreichen, wenn möglich.

Antwort

2

Ich würde kommentieren, aber ich habe noch keinen ausreichenden Ruf.

Ich habe studiert pg_search, die mich tiefer in PostgreSQL Volltextsuche geführt hat. Es ist ein komplexes Modul, aber es hat den Befehl ts_debug(), um zu verstehen, wie Eingabezeichenfolgen analysiert werden. Die Ausgabe von ts_debug() für die Testzeichenfolge "C++ CSS C# Objective C" ist sehr aufschlussreich. Es sieht aus wie „# und‚+‘als Leerraum in der Standardkonfiguration für Englisch behandelt. Ich denke, man könnte den Parser in PostgreSQL ändern, um das Verhalten Sie wollen.

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, ist hier ein sehr nützliches Tutorial, wenn Sie PostgreSQL Volltextsuche studieren: http://shisaa.jp/postset/postgresql-full-text-search-part-1.html

UPDATE:

ich eine Lösung innerhalb PostgreSQL Volltextsuche gefunden Es geht um die test_parser Erweiterung verwendet, die hier dokumentiert ist:. http://www.postgresql.org/docs/9.1/static/test-parser.html

Zunächst einige Konfiguration erforderlich in 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; 

Jetzt können Sie Index einen String-Test und sehen, dass die Begriffe wie "C++" als separate Token behandelt, je nach Wunsch:

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) 

Die Frage bleibt, wie man das in pg_search integriert. Ich sehe das als nächstes an.