2016-03-28 13 views
3

Ich muss Benutzer in meiner Neo4j-Datenbank basierend auf ihren Vor- und Nachnamen suchen. Die Abfrageergebnisse sollten nach ihrer Übereinstimmung mit der Suchanfrage sortiert sein. Wir erwarten, dass die Sucheingabe zwei Wörter ist (für den ersten/letzten oder letzten/ersten Namen).Neo4j - Bewertung basierend auf Eignung bei der Suche nach Benutzern

Die Abfrage, die wir bisher verwendet haben, sucht nach Benutzern, die den ersten Namen enthalten, und verwendet dann UNION ALL, um die Benutzer wieder zu finden, die jedoch den Nachnamen enthalten. Nehmen wir an, die Sucheingabe war "first last". Also unsere Frage ist:

MATCH (u:User) WHERE u.first_name =~'(?i).*first.*' RETURN u 
UNION ALL u.last_name =~'(?i).*last.*' return u 
UNION ALL u.first_name =~'(?i).*last.*' RETURN u 
UNION ALL u.last_name =~'(?i).*first.*' return u 

So ein Benutzer, der die Vornamen und den Nachnamen der Sucheingabe zweimal im Abfrageergebnis wird angezeigt hat. Dann im Java-Back-End zählen wir, wie oft jeder Benutzer erschien (jeder Benutzer hat einen eindeutigen Benutzernamen) und dann sortieren.

Ich möchte das Sortieren und Zählen im Java-Backend vermeiden und wenn möglich nur eine einzige Abfrage verwenden.

Jede Hilfe wäre willkommen. Danke.

Antwort

5

Mit einer textähnlichen Suchabfrage wird Chiffre wahrscheinlich nicht die Art sein, wie Sie dies tun wollen. Neo4j unterstützt tatsächlich Legacy-Indizes, die von Apache Lucene implementiert werden, und ich empfehle diese für Sie, weil es für die Textindizierung gedacht ist. Lucene bietet Ihnen sogar eine umfangreiche Abfragesprache, um Ihre Suche zu verbessern.

Wenn Sie versuchen, die Chiffre-Route zu gehen, werden Sie am Ende eine Menge komplexen Back-End-Code schreiben, und Ihre Matches sind immer noch ziemlich naiv; In diesem Beispiel benötigen Sie für den Nachnamen und den Vornamen immer noch eine zeichenweise Übereinstimmung, und beim Schließen von Rechtschreibfehlern wird kein Treffer gefunden.

Documentation for legacy indexing starts here. Lesen Sie unbedingt die Unterseite "Scoring", denn am Ende denke ich, dass Sie das wollen. Überprüfen Sie auch extra features for lucene indexing, weil es beginnt, Ihnen kühlere Sachen zu zeigen, die Sie (wie zusammengesetzte Abfragen) mit Lucene tun können, die über cypher nicht möglich sein werden.

Die gute Nachricht ist, dass neo4j das kann, und es funktioniert wirklich gut. Die schlechte Nachricht ist, dass einiges von diesem Zeug nur über die Java-API verfügbar ist, und Sie können es nicht direkt von der Chiffre aus tun, wie das von Ihnen angegebene Beispiel vermuten lässt.

1

Sie können sie auch in einem regexp kombinieren:

MATCH (u:User) 
WHERE (u.first_name+" "+u.last_name) =~'(?i).*(first|last).*' RETURN u 

Sie könnte besser sein, beide zusammen in einem „Namen“ Eigenschaft zu speichern. In Neo4j 3.x CONTAINS wird auch einen Index verwenden, aber ist zur Zeit Groß-und Kleinschreibung.

0

Eine Möglichkeit zur Überprüfung der rudimentären Übereinstimmungsgenauigkeit, die ich derzeit in einer Suchabfrage verwende, besteht darin, die Zeichenfolgenlänge des Suchschlüssels anhand der Ergebniszeichenfolge zu überprüfen und die Ergebnisliste nach der berechneten Differenz zu sortieren.

MATCH (u:User) WHERE u.name ~= {searchKeyRegex} 
RETURN u.name, ABS(LENGTH(u.name) - LENGTH({searchKey})) as precision 
ORDER BY precision ASC LIMIT {limit} 

Ich muss zugeben, das ist immer noch pritty rohe Gewalt, aber bis jetzt scheint es den Trick zu tun.

Verwandte Themen