优化neo4j cypher查询以检索社交新闻源

时间:2015-10-15 06:53:19

标签: php neo4j cypher 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 .

2 个答案:

答案 0 :(得分:2)

首先,您应该确保user_id标签的User属性上有索引。像这样:

CREATE INDEX ON :Users(user_id)

(顺便说一句,通常使用单数名词作为标签)

但你也应该使用Neo4j关系,而不是匹配帖子的created_by列。与检查索引相比,这将允许Neo4j遍历关系(这是非常快的)(我认为这仍然很快,但不是那么理想)

但我认为,你也有一个问题,即WHERE中的变量应该直接放在WHERE子句后面(OPTIONAL) MATCH。例如,您的(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,而不是使用标签。

答案 1 :(得分:0)

你应该使用Match(c)match(p:Posts)我的意思是使用多个匹配。 您还应该在User user_id上使用约束。

你不应该在where子句中使用() - [] - &gt;()。也许你可以使用可选的匹配。

您还应该对查询进行概要分析,以了解其行为方式。所以你可以减少db命中率。