通过这种方式捆绑我的密码查询,我是否遗漏了任何明显的优化?
是的。有问题的查询使查询优化器和执行引擎的工作变得极其困难。如果您使用 Web 浏览器运行带有 EXPLAIN 的查询计划,它会告诉您此查询计划需要大量元组,而这不是引擎构建的处理方式。
一般来说,循环节点以创建关系而不是捆绑它们是一种好习惯吗?
循环是一个很好的方向。事实上,您可以进行多种优化:
将[startNode, endNode, relationshipProperties] 三元组的集合作为单个参数传递给驱动程序和UWIND。
使用SET relationship_variable = map_variableconstruct初始化关系的属性。
或者,您可能希望使用collect 方法在列表中返回结果ID,但这通常不是必需的,因为驱动程序返回一个可迭代的结果。
这个查询包含了这些技巧:
UNWIND $rels AS rel
WITH
rel[0] AS startNodeId,
rel[1] AS endNodeId,
rel[2] AS relationshipProperties
MATCH (startNode:SomeLabel), (endNode:SomeLabel)
WHERE ID(startNode) = startNodeId
AND ID(endNode) = endNodeId
CREATE (startNode)-[r:`ParameterValue`]->(endNode1)
SET r = relationshipProperties
WITH collect(ID(r)) AS relationshipIds
RETURN relationshipIds
在客户端,您应该使用StatementRunner.run(statementTemplate, statementParameters) method 传递参数。只是一个带有rels 的单个键和一个三元素列表的映射。您可以使用好的集合库以简洁的方式表达这一点,例如 Guava 的immutable collections:
Map<String, Object> parameters =
ImmutableMap.of("rels",
ImmutableList.of(
ImmutableList.of(1, 2, ImmutableMap.of("prop1", "value1", "prop2", false)),
ImmutableList.of(3, 4, ImmutableMap.of(...)),
...
)
);
StatementRunner.run("UNWIND ...", parameters);
注意 1. Cypher 语言允许您将节点和关系作为参数传递。但是,这仅适用于嵌入式版本和not in the client-server setup,因此您最好传递 id。
注意 2. 话虽如此,传递内部 ID 是一种不好的做法。虽然它适用于大多数原型,但您可能需要考虑避免使用它们并提供您自己的标识符。见Best and Worst Practices with Node IDs。
注意 3. 除了使用三元组之外,您还可以使用映射来表示要创建的关系。这样,您将它们作为 Java 中的 Map 传递,即您的列表将包含地图:
ImmutableMap.of("startNode", 1, "endNode", 2, "relationshipProperties", ImmutableMap.of("prop1", "value1", "prop2", true))
然后您可以将这些值称为rel.startNode、rel.endNode 和rel.relationshipProperties。这使得查询的可读性和维护更容易一些,但通常不值得这么麻烦。