Reducing the cost of Cypher Query
我有一个简单的数据库,我用它来分析特定组的 Twitter 数据。
数据模型为:
和
我想计算关注关系的数量,但仅在与人相关的 500 个左右的 Twitter 帐户中。环顾四周,我发现了这篇 neo4j 博客文章和这篇 SO 文章,其中建议了这样的查询:
1 2 3 4 5 | MATCH (p:Person)-[:TWEETS_TO]->(t1:Twitter_Account) WITH t1, size((t1)-[:FOLLOWS]->(:Twitter_Account)<-[:TWEETS_TO]-(:Person)) AS following RETURN t1, following ORDER BY following LIMIT 5 |
分析给出:
Cypher version: CYPHER 3.2, planner: COST, runtime: INTERPRETED. 2938092 total db hits in 1356 ms.
如您所见,它相对较快,但我的直觉认为应该有办法编写查询,而无需太多数据库命中,因为我们只查看易于定义的数据的一小部分。我尝试过的所有其他方法(例如首先匹配两个 twitter 帐户)导致笛卡尔乘积比上面的要慢得多。
有没有办法在不查看每个 Twitter 帐户的情况下计算这些关系?
您应该只需要对
例如:
1 2 3 4 5 6 7 8 | MATCH (:Person)-[:TWEETS_TO]->(t1:Twitter_Account) WITH COLLECT(t1) AS accts UNWIND accts AS acct OPTIONAL MATCH (acct)-[:FOLLOWS]->(t2) WHERE t2 IN accts RETURN acct, COUNT(t2) AS following ORDER BY following LIMIT 5 |
在这个查询中,我们找到了
您可能需要考虑为与人相关的 :Twitter_Accounts 添加一个单独的标签,以使您以后的查询更容易。
1 2 3 | MATCH (t:Twitter_Account) WHERE exists(()-[:TWEETS_TO]->(t)) SET t:Connected_Account |
如果您的图表需要处理更新,那么您需要确保添加了新帐户,检查是否连接了 :Person 并相应地添加标签。
一旦到位,您稍后的查询将变为:
1 2 3 4 5 | MATCH (t1:Connected_Account) WITH t1, size((t1)-[:FOLLOWS]->(:Connected_Account)) as following RETURN t1, following ORDER BY following LIMIT 5 |
如果只有 500 个 :Connected_Account 节点,那么这应该会大大减少您的数据库命中并加快您的查询速度。