我有一个简单的图形模型。在此图表中,每个节点都有一个属性 {NodeId} 。每个Edge将链接两个节点而没有其他属性。它是一个有向图,有大约10 ^ 6个节点。
这是我的情况: 我首先在属性 {NodeId} 上创建了索引。然后我创建了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条边。
答案 0 :(得分:3)
理想的解决方案是在一个参数映射中传递要关联的节点对,然后使用UNWIND,您可以迭代这些对并创建关系,只要您在{{1}上有索引,这就非常有效。 Id
节点的属性。
我不知道你怎么能用Neo4jClient做到这一点,但这里是Cypher声明:
Node
要与查询一起发送的参数应具有以下形式:
UNWIND {pairs} as pair
MATCH (a:Node), (b:Node)
WHERE a.Id = pair.start AND b.Id = pair.end
CREATE (a)-[:EDGE]->(b)
<强>更新强>
Neo4jClient作者在Neo4jClient中给了我相同的代码:
{
"parameters": {
"pairs": [
{
"start": "1",
"end": "2"
},
{
"start": "3",
"end": "4"
}
]
}
}
答案 1 :(得分:0)
在您更新的Cypher查询中,您MATCH
是所有节点的笛卡尔积。那很慢。看看the EXPLAIN
of your query。
请参阅此问题,了解如何处理笛卡儿产品:Why does neo4j warn: "This query builds a cartesian product between disconnected patterns"?
你有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)