2015-10-15 37 views
1

到目前爲止,我已經嘗試過這個查詢,但它掃描所有節點的速度非常慢。它能夠是我想要檢索優化neo4j密碼查詢以檢索社交新聞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 . 

回答

0

你應該使用匹配(三)比賽(P:帖子),我的意思是使用多個比賽。 另外你應該對用戶user_id使用約束。

你不應該在where子句中使用() - [] - >()。也許你可以使用可選的Match。

您還應該剖析您的查詢以瞭解其行爲。所以你可以減少你的db命中。

+0

你會說出你在說什麼嗎?請給出一個簡短的片段 –

+0

有很多情況下你想在WHERE子句中指定一個模式。 –

2

首先,您應該確保您有User標籤的user_id屬性的索引。就像這樣:

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,而不是使用標籤。

+0

如果仍然有問題,請嘗試共享查詢的「PROFILE」 –

+0

是的,我已經在user_id,post_id和其他id相關的字段上建立了索引 –

+0

確實對sql有很好的體驗,這就是爲什麼我達到了這麼高的水平的cql,但實際上我只有10天neo4j的經驗,並且你的意思是'查詢時間'由PROFILE –