尽管指数缓慢Neo4j查询

时间:2014-08-11 03:50:44

标签: performance neo4j cypher

在这里,我试图找到所有跟随并跟随某个组G成员的Twitter用户:

MATCH (x:User)-[:FOLLOWS]->(t:User)-[:FOLLOWS]->(y:User)
WHERE (x.screen_name IN {{G_SCREEN_NAMES}} OR x.id IN {{G_IDS}})
  AND (y.screen_name IN {{G_SCREEN_NAMES}} OR y.id IN {{G_IDS}})
RETURN t.id

但是对于组G我有时会有他们的屏幕名称,有时会有他们的ID,因此上面是OR子句。不幸的是,这个查询已经运行很长时间,并且似乎无法返回。

我在idscreen_name上都有索引和约束:

Indexes
  ON :User(screen_name) ONLINE (for uniqueness constraint) 
  ON :User(id)          ONLINE (for uniqueness constraint) 

Constraints
  ON (user:User) ASSERT user.screen_name IS UNIQUE
  ON (user:User) ASSERT user.id IS UNIQUE

如果我摆脱了OR子句(例如,如果我碰巧拥有G组的所有screen_names或所有id),那么查询运行得非常快。

我在Mac上使用neo4j-community-2.1.3。我的图表有286039个节点,所有节点都有User标签。

想要改进这个吗?否则,我必须将其分为4个查询以获得所有可能的成员组合。这确实更成问题,因为我真的想跟踪用户>用户 - > G关系中通常的出现方式,我还需要做如果计数分布在4个不同的查询中,那么需要额外的大量记账。

更新

我创建了一个与此相关的问题:https://github.com/neo4j/neo4j/issues/2834

我最终使用

MATCH (x:User) WHERE x.screen_name IN ["apple","banana","coconut"] 
WITH collect(id(x)) as x_ids
MATCH (x:User) WHERE x.id in [12345,98765]
WITH x_ids+collect(id(x)) as x_ids

MATCH (y:User) WHERE y.screen_name IN ["apple","banana","coconut"] 
WITH x_ids,collect(id(y)) as y_ids
MATCH (y:User) WHERE y.id in [12345,98765]
WITH x_ids,y_ids+collect(id(y)) as y_ids

MATCH (x:User)-[:FOLLOWS]->(t:User)-[:FOLLOWS]->(y:User)
WHERE id(x) in x_ids AND id(y) in y_ids
RETURN count(*) as c, t.screen_name,t.id
ORDER BY c DESC
LIMIT 1000

但这基本上代表了一个黑客来绕过neo4j并没有使用它可能的指数。

2 个答案:

答案 0 :(得分:3)

我认为由于OR条件,查询没有使用索引,您可以通过在查询前添加PROFILE来验证并在neo4j-shell中运行它。

如果没有索引使用的概念,您可以将查询分成两部分。第一个获取用户ID的组合列表,而不是OR,我们对两个查询(每个使用索引查找)执行UNION:

MATCH (x:User) WHERE x.screen_name in {G_SCREEN_NAMES} RETURN id(x) as ids UNION
MATCH (x:User) WHERE x.id in {G_IDS} RETURN id(x) as ids

在客户端,使用节点ID列表作为下一个查询的参数:

MATCH (x:User)-[:FOLLOWS]->(t)-[:FOLLOWS]->(y)
WHERE id(x) in {ids} AND id(y) in {ids}
RETURN t.id

我故意删除了ty的标签,并假设您只能关注User而没有其他类型的节点。这将删除不必要的标签检查。

答案 1 :(得分:2)

JnBrymn,

这个查询怎么样?

MATCH (x:User)
WHERE x.screen_name IN {{G_SCREEN_NAMES}} OR x.id IN {{G_IDS}}
WITH x
MATCH (x)-[:FOLLOWS]->(t:User)
WITH t
MATCH (t)-[:FOLLOWS]->(y:User)
WHERE y.screen_name IN {{G_SCREEN_NAMES}} OR y.id IN {{G_IDS}}
RETURN t.id

恩典与和平,

吉姆