使用Neo4j 3.0.4
如果路径上存在可选匹配项,则有条件地创建顶点:
with [
{customer: 0001, created: 1474434591, version: "1.0.0"},
{customer: 0001, created: 1474434500, version: "1.0.0"},
{customer: 0003, created: 1474445743, version: "1.1.0"}
] as lines
unwind lines as line
/// customers above already exist
MATCH (c:Customer {id: line.customer})
OPTIONAL MATCH (c)-[:HAS]->(co:Configuration) WHERE co.created >= line.created
WITH CASE WHEN co IS NULL THEN
[1]
END as createInventory,
CASE WHEN co IS NOT NULL THEN
[count(co)]
END as throwError, c, line
FOREACH (x in createInventory |
CREATE (n:Configuration {
created: line.created,
version: line.version
})
CREATE UNIQUE (c)-[:HAS]->(n)
)
FOREACH (x in throwError |
CREATE (e:Error:Inventory { message: "Configuration " + line.created + " >= existing (" + x + ")" })
);
期望只创建2 Configuration
个顶点并与Customer
相关联。而是创建了所有3个Configuration
个实例。写语句(即create)在同一个事务中,因此我假设在循环OPTIONAL MATCH
时不反映单个写操作。在此示例中,行是Configuration
,如果创建的属性比现有属性旧,我不想创建与同一Customer
绑定的新行。因此OPTIONAL MATCH
中的谓词。
在同一事务(或Cypher语句)中有条件地创建和考虑写入的任何方式?
答案 0 :(得分:2)
Cypher永远不会"循环"回到之前的条款。
您可以通过在UNWIND
子句后面插入此子句来获得您的期望:
WITH
line.customer AS lc,
REDUCE(s = NULL, x IN COLLECT(line) | CASE WHEN s IS NULL OR x.created > s.created THEN x ELSE s END) AS line
此WITH
子句根据不同的line.customer
值获取line
值created
,删除任何其他行。 (这是"每个客户"的原因是因为使用了COLLECT
aggregation function within that WITH clause)。
顺便说一句,您的查询使用CREATE UNIQUE
而不是CREATE
是没有意义的,因为之前创建的n
节点是全新的,因此指定的模式以前不存在。