繁体   English   中英

Neo4j是否可以在一个密码查询中创建可变数量的关系?

[英]Neo4j is there a way to create a variable number of relationships in one cypher query?

我想创建N个节点,每个节点之间具有顺序关系。

认为我的要求是为用户创建工作流程。 在UI端,它可以发送必须顺序相关的json对象数组。 例如:

{steps: [ {name: 'step 1'}, {name: 'step2'}, {name: 'step3'}] }

我从上面的json想要的是创建3个节点,并将它们顺序链接

(step 1)-[:has_next_step]->(step 2)-[:has_next_step]->(step 3)

有快速的方法吗? 请记住,我的示例有3个节点,但实际上我可能有5-15个步骤,因此密码查询必须能够处理此变量输入。 请注意,我也可以控制输入,因此,如果有一个更简单的json params变量,我也可以使用它。

您可以遇到的唯一问题是,在迭代步骤集合时,您将无法识别集合中之前代表该元素的节点。

因此,您可以在查询开始时使用时间戳作为标识符:

WITH {steps: [ {name: 'step 1'}, {name: 'step2'}, {name: 'step3'}] } AS object
WITH object.steps AS steps, timestamp() AS identifier
UNWIND range(1, size(steps)-1) AS i
MERGE (s:Step {id: identifier + "_" + (i-1)}) SET s.name = (steps[i-1]).name
MERGE (s2:Step {id: identifier + "_" + (i)}) SET s2.name = (steps[i]).name
MERGE (s)-[:NEXT]->(s2)

说明:

我使用UNWIND迭代步骤UNWIND ,以便识别代表已迭代步骤的每个节点,我使用了一个虚拟标识符作为事务的时间戳+“ _” +序列游标。

大规模使用时,最好使用自己的标识符(例如在客户端生成的uuid)并对其具有索引/唯一约束。

在此处输入图片说明

更先进 :

您有一个“用户”节点,并希望将步骤附加到该节点(上下文:该用户之前未连接任何步骤)

创建一个虚拟用户:

CREATE (u:User {login:"me"})

创建步骤列表并附加到用户

WITH {steps: [ {name: 'step 1'}, {name: 'step2'}, {name: 'step3'}] } AS object
WITH object.steps AS steps, timestamp() AS identifier
UNWIND range(1, size(steps)-1) AS i
MERGE (s:Step {id: identifier + "_" + (i-1)}) SET s.name = (steps[i-1]).name
MERGE (s2:Step {id: identifier + "_" + (i)}) SET s2.name = (steps[i]).name
MERGE (s)-[:NEXT]->(s2)
WITH identifier + "_" + (size(steps)-1) AS lastStepId, identifier + "_0" AS firstStepId
MATCH (user:User {login:"me"})
OPTIONAL MATCH (user)-[r:LAST_STEP]->(oldStep)
DELETE r
WITH firstStepId, lastStepId, oldStep, user
MATCH (s:Step {id: firstStepId})
MATCH (s2:Step {id: lastStepId})
MERGE (user)-[:LAST_STEP]->(s)
WITH s2, collect(oldStep) AS old
FOREACH (x IN old | MERGE (s2)-[:NEXT]->(x))

在此处输入图片说明

上下文,(运行相同的查询,但使用不同的名称来直观地看到差异的步骤):用户已经附加了步骤:

WITH {steps: [ {name: 'second 1'}, {name: 'second 2'}, {name: 'second 3'}] } AS object
WITH object.steps AS steps, timestamp() AS identifier
UNWIND range(1, size(steps)-1) AS i
MERGE (s:Step {id: identifier + "_" + (i-1)}) SET s.name = (steps[i-1]).name
MERGE (s2:Step {id: identifier + "_" + (i)}) SET s2.name = (steps[i]).name
MERGE (s)-[:NEXT]->(s2)
WITH identifier + "_" + (size(steps)-1) AS lastStepId, identifier + "_0" AS firstStepId
MATCH (user:User {login:"me"})
OPTIONAL MATCH (user)-[r:LAST_STEP]->(oldStep)
DELETE r
WITH firstStepId, lastStepId, oldStep, user
MATCH (s:Step {id: firstStepId})
MATCH (s2:Step {id: lastStepId})
MERGE (user)-[:LAST_STEP]->(s)
WITH s2, collect(oldStep) AS old
FOREACH (x IN old | MERGE (s2)-[:NEXT]->(x))

在此处输入图片说明

您可以使用几个APOC过程来创建节点,然后将它们链接在一起:

  • apoc.create.nodes可用于创建具有相同标签的多个节点。
  • apoc.nodes.link可用于将节点与相同类型的关系链接在一起。

例如,下面的查询将创建您的3个示例节点(带有“ Step标签),然后使用has_next_step关系按顺序将它们链接在一起:

CALL apoc.create.nodes(['Step'],[{name:'step1'},{name:'step2'},{name: 'step3'}]) YIELD node
WITH COLLECT(node) AS nodes
CALL apoc.nodes.link(nodes, 'has_next_step')
RETURN SIZE(nodes)

apoc.nodes.link过程不返回任何内容,因此上面的查询仅返回已创建并链接在一起的节点数。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM