2016-03-28 70 views
3

我需要根據姓名和姓氏在我的neo4j數據庫中搜索用戶。 查詢結果應按照它們與搜索查詢匹配的程度排序。 我們希望搜索輸入是兩個單詞(第一個/最後一個或最後一個/名字)。Neo4j - 基於搜索用戶時的適用性得分

到目前爲止我們使用的查詢搜索包含名字的用戶,然後使用UNION ALL再次匹配用戶,但是包含姓氏。 假設搜索輸入是「第一」。 所以我們的查詢是:

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 

所以有名字和搜索輸入的姓氏,用戶將在查詢結果中出現兩次。 然後在java後端,我們計算每個用戶出現的次數(每個用戶都有一個唯一的用戶名),然後進行排序。

我想避免在java後端進行排序和計數,只要可能就簡單地使用單個查詢。

任何幫助,將不勝感激。 謝謝。

回答

5

對於類似於文本的搜索查詢,密碼可能不會成爲您想要執行此操作的方式。 Neo4j實際上支持由Apache Lucene實現的遺留索引,我推薦那些適合你的索引,因爲它是用於文本索引的。 Lucene甚至爲您提供豐富的查詢語言以改善您的搜索。

如果你嘗試去密碼路線,你最終會寫很多複雜的後端代碼,你的匹配仍然很樸素;在這個例子中,你仍然需要在姓和名之間進行一個字符匹配的匹配,並且關閉拼寫錯誤不會找到匹配。

Documentation for legacy indexing starts here。請務必閱讀「評分」的子頁面,因爲最終,我認爲這就是你想要的。另外請確保檢查extra features for lucene indexing,因爲它將開始向你展示你可以做的更酷的事情(比如複合查詢),通過使用Lucene將無法通過密碼進行。

好消息是,neo4j可以做到這一點,它的工作非常好。壞消息是有些東西只能通過java API獲得,並且你不能直接從cypher那裏獲得,就像你提供的例子一樣。

1

您還可以將其合併成一個正則表達式:

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

你可能會既在「名稱」屬性的放在一起保存好。 在Neo4j 3.x CONTAINS也將使用索引,但目前區分大小寫。

0

檢查基本匹配精度的一種方法我目前在搜索查詢中使用的方法是簡單地根據結果字符串檢查搜索關鍵字的字符串長度,然後按計算出的差異對結果列表進行排序。

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

我不得不承認,這仍然是pritty蠻力,但到目前爲止,它似乎是伎倆。