如何在非常大的图中添加边(关系)Neo4j

How to add edges(relationship) Neo4j in a very big graph

我有一个简单的图形模型。在此图中,每个节点都有一个属性 {NodeId}。每个 Edge 将 link 两个没有其他属性的节点。它是一个有向图,大约有 10^6 个节点。

这是我的情况: 我在属性 {NodeId} 上创建了索引 first.Then 我创建了 10^6 个节点。这次,我有一个包含 10^6 个节点且没有边的图。 当我想随机添加边时,发现速度很慢。我每秒只能添加大约 40 个边。

我是否遗漏了任何配置?我不认为这是一个合理的速度。

加边代码:

public static void addAnEdge(GraphClient client, Node a, Node b)
    {
        client.Cypher
        .Match("(node1:Node)", "(node2:Node)")
        .Where((Node node1) => node1.Id == a.Id)
        .AndWhere((Node node2) => node2.Id == b.Id)
        .Create("node1-[:Edge]->node2")
        .ExecuteWithoutResults();
    }

我应该在边上添加索引吗?如果是这样,如何在 neo4jClient 中执行? 感谢您的帮助。


将我所有的查询集中到一个事务中是一个很好的选择。我在浏览器中执行以下语句(http://localhost:7474):

MATCH (user1:Node), (user2:Node)
WHERE user1.Id >= 5000000 and user1.Id <= 5000100 and user2.Id >= 5000000 and user2.Id <= 5000100
CREATE user1-[:Edge]->user2

在这个语句中,我在一个事务中创建了 10000 个边缘。所以我觉得现在http开销没有那么严重了。结果是:

Created 10201 relationships, statement executed in 322969 ms.

这意味着我每秒添加 30 个边。

在您更新的 Cypher 查询中,您 MATCH 所有 个节点的笛卡尔积。那很慢。看看 the EXPLAIN of your query.

并查看此问题以了解如何处理笛卡尔积:

你有 Id 属性 的索引吗?理想情况下,您应该 use a uniqueness constraint。这会自动添加一个非常快的索引。

在您的查询中,尝试首先 MATCH 第一批节点,使用 WITH 将它们收集到列表中,然后 MATCH 第二批节点:

MATCH (user1:Node)
WHERE user1.id >= 50000 and user1.id <= 50100
WITH collect(user1) as list1
MATCH (user2:Node)
WHERE user2.id >= 50000 and user2.id <= 50100
UNWIND list1 as user1
CREATE (user1)-[:EDGE]->(user2)

理想的解决方案是在一个参数映射中传递要关联的节点对,然后使用 UNWIND 您可以迭代这些对并创建关系,只要您在 [= Node 个节点的 13=] 属性。

我不知道你如何使用 Neo4jClient 做到这一点,但这是 Cypher 声明:

UNWIND {pairs} as pair
MATCH (a:Node), (b:Node)
WHERE a.Id = pair.start AND b.Id = pair.end
CREATE (a)-[:EDGE]->(b)

与查询一起发送的参数应采用以下形式:

{
  "parameters": {
    "pairs": [
      {
        "start": "1",
        "end": "2"
      },
      {
        "start": "3",
        "end": "4"
      }
    ]
  }
}

更新

Neo4jClient 作者好心地给了我 Neo4jClient 中的等效代码:

var parameters = new [] {
       new {start = 1, end = 2},
       new {start = 3, end = 4}
   };

   client.Cypher
       .Unwind(parameters, "pair")
       .Match("(a:Node),(b:Node)")
       .Where("a.Id = pair.start AND b.Id = pair.end")
       .Create("(a)-[:EDGE]->(b)")
       .ExecuteWithoutResults();