我有一个 Neo4j 数据库,它有两种不同的节点类型,一种用于爆破孔数据,一种用于地质块模型。我花了很大的努力来导入这些节点的数据以从 csv 填充,但我能够通过 CALL 方法实现这一点。块模型有大约 300 万个节点,可能有 12 个属性,爆破孔样本节点有大约 30k。我正在努力想出一个有效的查询来创建存储计算距离的空间关系。
我能够运行以下查询。
CALL apoc.periodic.iterate(
"MATCH (b:BlastholeSamples) RETURN b" LIMIT 100,
"WITH b
MATCH (g:GeologicalBlock)
WHERE g.location.x >= b.location.x - 100 AND g.location.x <= b.location.x + 100
AND g.location.y >= b.location.y - 100 AND g.location.y <= b.location.y + 100
AND point.distance(b.location, g.location) <= 100
AND abs(b.midZ_D - g.ELEV) < 0.5
WITH b, g, point.distance(b.location, g.location) AS distance
CREATE (b)-[r:LOCATED_IN {distance: distance}]->(g)",
{batchSize: 50, iterateList: true}
);
目的是在炮孔样本周围创建一个边界框以进行关系评估。如果地质块点在框中,则创建关系并存储距离。
在此查询之前,我确实根据 x、y、z 值创建了索引,并为笛卡尔创建了位置属性。
该查询不可能是最佳的,因为在我终止它之前它运行了超过 18 小时。这似乎太长了。
它似乎确实有效,并为某些节点生成了结果,这非常棒。
绽放图像
请帮助优化或提供一些我可能错过的提示?我是 neo4j 和 cypher 的超级新手。
我假设您为 GeologicalBlock.location
创建了一个
POINT 索引。 POINT 索引仅由某些空间函数使用(请参阅链接中的
Supported predicates
表)。因此,您应该:(1) 存储 3D 点(如果您尚未这样做),并且 (2) 使用 point.withinBBox()
预过滤点。
例如,假设
BlastholeSamples.location
和 GeologicalBlock.location
存储为“笛卡尔 3D”点,这样的方法可能适合您:
CALL apoc.periodic.iterate(
"MATCH (b:BlastholeSamples) RETURN b.location AS loc LIMIT 100",
"MATCH (g:GeologicalBlock)
WHERE point.withinBBox(g.location,
point({x: loc.x-100, y: loc.y-100, z: loc.z-100}),
point({x: loc.x+100, y: loc.y+100, z: loc.z+100}))
AND point.distance(loc, g.location) <= 100
CREATE (b)-[r:LOCATED_IN {distance: point.distance(loc, g.location)}]->(g)",
{batchSize: 50, iterateList: true}
);