Neo4j:特定关系与一般关系+属性
為了在Neo4j查詢中獲得最佳的遍歷速度,我們應該使關系類型盡可能具體 。
讓我們看一下幾周前我在Skillsmatter上發表的“ 建模建議引擎建模 ”演講中的一個例子。
我需要決定如何為成員和事件之間的“ RSVP”關系建模。 一個人可以對事件表示“是”或“否”,我想同時捕捉這兩個響應。
即我們可以選擇:
和:
在確定模型時,我們主要需要考慮我們要編寫的查詢的類型。 我們不應該忘記更新模型,但是根據我的經驗,查詢圖要比更新它們花費更多的時間。
讓我們依次看一下其中的每個:
我們要寫什么查詢?
第一個查詢將使用以前的“是” RSVP作為將來事件的關注指標。 我們對此查詢的“否” RSVP不感興趣。
我從具有“ response”屬性的通用RSVP關系類型開始,以區分“是”和“否”:
MATCH (member:Member {name: "Mark Needham"}) MATCH (futureEvent:Event) WHERE futureEvent.time >= timestamp() MATCH (futureEvent)<-[:HOSTED_EVENT]-(group)OPTIONAL MATCH (member)-[rsvp:RSVPD {response: "yes"}]->(pastEvent)<-[:HOSTED_EVENT]-(group) WHERE pastEvent.time < timestamp()RETURN group.name, futureEvent.name, COUNT(rsvp) AS previousEvents ORDER BY previousEvents DESC這運行得相當快,但是我很好奇是否可以通過更改為更具體的模型來使查詢更快地運行。 使用更具體的關系類型,我們的查詢顯示為:
MATCH (member:Member {name: "Mark Needham"}) MATCH (futureEvent:Event) WHERE futureEvent.time >= timestamp() MATCH (futureEvent)<-[:HOSTED_EVENT]-(group)OPTIONAL MATCH (member)-[rsvp:RSVP_YES]->(pastEvent)<-[:HOSTED_EVENT]-(group) WHERE pastEvent.time < timestamp()RETURN group.name, futureEvent.name, COUNT(rsvp) AS previousEvents ORDER BY previousEvents DESC現在,我們可以分析查詢并比較兩個解決方案的數據庫匹配:
RSVPD {response: "yes"} Cypher version: CYPHER 2.3, planner: COST. 688635 total db hits in 232 ms.RSVP_YES Cypher version: CYPHER 2.3, planner: COST. 559866 total db hits in 207 ms.因此,通過使用更具體的關系類型,我們會獲得一點收益。 數據庫命中率較低的原因部分是因為我們不再需要在每個“ RSVP”屬性上查找“ response”屬性并檢查其是否與“ yes”匹配。 我們還評估了較少的關系,因為我們只查看正向的RSVP,負向的被忽略。
我們的下一個查詢可能是捕獲成員發出的所有RSVP,并在事件旁邊列出它們:
MATCH (member:Member {name: "Mark Needham"})-[rsvp:RSVPD]->(event) WHERE event.time < timestamp() RETURN event.name, event.time, rsvp.response ORDER BY event.time DESCMATCH (member:Member {name: "Mark Needham"})-[rsvp:RSVP_YES|:RSVP_NO]->(event) WHERE event.time < timestamp() RETURN event.name, event.time, CASE TYPE(rsvp) WHEN "RSVP_YES" THEN "yes" ELSE "no" END AS response ORDER BY event.time DESC再次,我們看到了更具體的關系類型的少量數據庫命中率:
RSVPD {response: "yes"} / RSVPD {response: "no"} Cypher version: CYPHER 2.3, planner: COST. 684 total db hits in 37 ms.RSVP_YES / RSVP_NO Cypher version: CYPHER 2.3, planner: COST. 541 total db hits in 24 ms.但是,查詢非常麻煩,除非我們將響應存儲為關系的屬性,否則返回“ yes”或“ no”的代碼會有些尷尬。 如果引入了我們選擇排除的“ waitlist” RSVP,則更具體的方法查詢將變得更加痛苦。
我們需要更新關系嗎?
是! 用戶可以在事件發生之前更改其RSVP,因此我們需要能夠進行處理。
讓我們看一下使用兩種模型處理RSVP更改時必須編寫的查詢:
通用關系類型
MATCH (event:Event {id: {event_id}}) MATCH (member:Member {id: {member_id}}) MERGE (member)-[rsvpRel:RSVPD {id: {rsvp_id}}]->(event) ON CREATE SET rsvpRel.created = toint({mtime}) ON MATCH SET rsvpRel.lastModified = toint({mtime}) SET rsvpRel.response = {response}具體關系類型
MATCH (event:Event {id: {event_id}}) MATCH (member:Member {id: {member_id}})FOREACH(ignoreMe IN CASE WHEN {response} = "yes" THEN [1] ELSE [] END |MERGE (member)-[rsvpYes:RSVP_YES {id: {rsvp_id}}]->(event)ON CREATE SET rsvpYes.created = toint({mtime})ON MATCH SET rsvpYes.lastModified = toint({mtime})MERGE (member)-[oldRSVP:RSVP_NO]->(event)DELETE oldRSVP )FOREACH(ignoreMe IN CASE WHEN {response} = "no" THEN [1] ELSE [] END |MERGE (member)-[rsvpNo:RSVP_NO {id: {rsvp_id}}]->(event)ON CREATE SET rsvpNo.created = toint({mtime})ON MATCH SET rsvpNo.lastModified = toint({mtime})MERGE (member)-[oldRSVP:RSVP_YES]->(event)DELETE oldRSVP )如您所見,使用特定的關系類型時,更新RSVP的代碼更加復雜,部分原因是Cypher尚未對條件提供一流的支持。
總而言之,對于我們的metup.com模型,我們通過使用更具體的關系類型獲得了速度上的提高,但是卻以一些更復雜的讀取查詢和更為復雜的更新查詢為代價。
根據模型中關系的基數,您的里程可能會有所不同,但是值得進行一些分析以比較所有選項。
翻譯自: https://www.javacodegeeks.com/2015/12/neo4j-specific-relationship-vs-generic-relationship-property.html
總結
以上是生活随笔為你收集整理的Neo4j:特定关系与一般关系+属性的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux消息队列(linux 消息)
- 下一篇: 安卓小车控制(安卓小车)