[英]Optimising neo4j cypher query for retrieving a social news feed
到目前為止,我已經嘗試過該查詢,但是由於掃描所有節點,它確實很慢。 它具有我想要檢索的功能
match (u:Users{user_id:140}),(p:Posts),(pu:Users{user_id:p.created_by}) optional match (p)-[:POST_MEDIA]->(f) optional match (p)-[:COMMENT]->(c)<-[:COMMENT]-(u3)
where
(p)-[:CREATED_BY]->(u) or (p:PUBLIC and (u)-[:FOLLOW]->(pu) )or (p:PRIVATE and (p)-[:SHARED_WITH]->(u))
return {user_id:pu.user_id,firstname:pu.firstname,lastname:pu.lastname,profile_photo:pu.profile_photo,username:pu.username} as pu,p,collect({user_id:u3.user_id,profile_photo:u3.profile_photo,text:c.text}) as comment,collect(f) as file order by p.post_id DESC limit 25
在執行此查詢之前,我嘗試了此查詢,該查詢速度非常快,但無法檢索完整的新聞提要,它只能從關注者中檢索帖子,而不僅是用戶本人,還不能從其他用戶的私人帖子中檢索與新聞提要的用戶共享的私人帖子。
match (u:Users{user_id:140})-[:FOLLOW]->(pu)<-[:CREATED_BY]-(p:Posts)
optional match (p)-[:POST_MEDIA]->(f)
optional match (p)-[:COMMENT]->(c)<-[:COMMENT]-(u3) where p:PUBLIC
return
{user_id:pu.user_id,firstname:pu.firstname,
lastname:pu.lastname,profile_photo:pu.profile_photo,username:pu.username} as pu,p,
collect({user_id:u3.user_id,profile_photo:u3.profile_photo,text:c.text}) as comment,
collect(f) as file order by p.post_id DESC limit 25
注意:-只需像這樣修改where子句:-
where p:PUBLIC or (p)-[:SHARED_WITH]->(u)
// but the only problem is that how i should include posts of users himself which is retrieving news feed .
首先,您應確保在user_id
屬性上有一個用於User
標簽的索引。 像這樣:
CREATE INDEX ON :Users(user_id)
(順便說一句,在標簽上使用單數名詞是常見的做法)
但是,您還應該使用Neo4j關系,而不是通過帖子的created_by
列進行匹配。 與檢查索引相比,Neo4j可以遍歷關系(非常快)(索引仍然很快,但我認為不是理想的)
但是,我認為您還有一個問題,那就是應該將WHERE
中的變量直接放在有問題的(OPTIONAL) MATCH
之后的WHERE
子句中。 例如,您的(p)-[:CREATED_BY]->(u)
條件引用了第一個MATCH
定義的變量,但是它們位於OPTIONAL MATCH
之下,而WHERE
實際上將應用於OPTIONAL MATCH
。 盡管您希望對性能進行基准測試,但您應該能夠通過在其之間插入WITH *
來解決此問題。
這是其中一些更改的查詢(不是您首先需要分別設置CREATED
關系):
MATCH
(u:Users {user_id:140}),
(p:Posts)<-[:CREATED]-(pu:Users)
WHERE
(p)-[:CREATED_BY]->(u) OR
(p:PUBLIC AND (u)-[:FOLLOW]->(pu)) OR
(p:PRIVATE AND (p)-[:SHARED_WITH]->(u))
OPTIONAL MATCH (p)-[:POST_MEDIA]->(f)
OPTIONAL MATCH (p)-[:COMMENT]->(c)<-[:COMMENT]-(u3)
RETURN
{user_id:pu.user_id,
firstname:pu.firstname,
lastname:pu.lastname,
profile_photo:pu.profile_photo,
username:pu.username} as pu,
p,
collect({user_id:u3.user_id,
profile_photo:u3.profile_photo,
text:c.text}) as comment,
collect(f) as file
ORDER BY p.post_id DESC LIMIT 25
編輯 :實際上,看着這個, WHERE
中的所有變量都在第一個MATCH
中定義,因此您應該能夠將其向上移動。 編輯查詢以反映這一點。
EDIT2 :您可以嘗試使用OPTIONAL MATCH
,我認為它將讓Neo4j首先進行遍歷。 我認為有了WHERE
,它會獲得所有可能的結果,然后進行過濾,效果可能不那么有效。
PROFILE
MATCH
(u:Users {user_id:140}),
(p:Posts)<-[:CREATED]-(pu:Users)
OPTIONAL MATCH (p)-[created_by:CREATED_BY]->(u), (u)-[follow:FOLLOW]->(pu), (p)-[shared_with:SHARED_WITH]->(u)
WHERE created_by IS NOT NULL OR (p:PUBLIC AND follow IS NOT NULL) OR (p:PRIVATE AND shared_with IS NOT NULL)
OPTIONAL MATCH (p)-[:POST_MEDIA]->(f)
OPTIONAL MATCH (p)-[:COMMENT]->(c)<-[:COMMENT]-(u3)
RETURN
{user_id:pu.user_id,
firstname:pu.firstname,
lastname:pu.lastname,
profile_photo:pu.profile_photo,
username:pu.username} as pu,
p,
collect({user_id:u3.user_id,
profile_photo:u3.profile_photo,
text:c.text}) as comment,
collect(f) as file
ORDER BY p.post_id DESC LIMIT 25
您可能還想嘗試使用索引屬性來指示private
屬性,而不是使用標簽。
您應該使用Match(c)match(p:Posts)我的意思是使用多個匹配項。 另外,您應該對用戶user_id使用約束。
您不應在where子句中使用()-[]->()。 也許您可以使用可選的匹配。
您還應該配置查詢以查看其行為。 因此,您可以減少數據庫命中率。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.