Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/meteor/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Neo4j有没有办法在一个密码查询中创建数量可变的关系?_Neo4j_Cypher - Fatal编程技术网

Neo4j有没有办法在一个密码查询中创建数量可变的关系?

Neo4j有没有办法在一个密码查询中创建数量可变的关系?,neo4j,cypher,Neo4j,Cypher,我想创建N个节点,每个节点之间都有顺序关系 将我的需求视为为为用户创建工作流。在UI端,它可以发送json对象数组,这些对象必须按顺序相互关联。例如: {steps:[{name:'step1'},{name:'step2'},{name:'step3'}]} 我希望从上面的json中创建3个节点,并将它们按顺序链接起来 (步骤1)-[:has_next_step]->(步骤2)-[:has_next_step]->(步骤3) 有没有快速的方法?请记住,我的示例有3个节点,但实际上我可能有5到1

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

将我的需求视为为为用户创建工作流。在UI端,它可以发送json对象数组,这些对象必须按顺序相互关联。例如:

{steps:[{name:'step1'},{name:'step2'},{name:'step3'}]}

我希望从上面的json中创建3个节点,并将它们按顺序链接起来

(步骤1)-[:has_next_step]->(步骤2)-[:has_next_step]->(步骤3)


有没有快速的方法?请记住,我的示例有3个节点,但实际上我可能有5到15个步骤,因此cypher查询必须能够处理这个变量输入。请注意,我也可以控制输入,因此如果有一个更简单的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
迭代步骤集合,为了识别表示已迭代步骤的每个节点,我使用伪标识符作为事务的时间戳+序列光标“”+

在大规模情况下,您最好使用自己的标识符(如客户端上生成的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))

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

因此,稍加修改,您可以在查询的开头使用时间戳作为标识符:

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
迭代步骤集合,为了识别表示已迭代步骤的每个节点,我使用伪标识符作为事务的时间戳+序列光标“”+

在大规模情况下,您最好使用自己的标识符(如客户端上生成的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个示例节点(带有
步骤
标签),然后使用
下一步
关系将它们按顺序链接在一起:

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
过程不返回任何内容,因此上面的查询只返回创建并链接在一起的节点数。

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

  • apoc.create.nodes
    可用于创建具有相同标签的多个节点
  • apoc.nodes.link
    可用于将节点与相同类型的关系链接在一起
例如,下面的查询将创建3个示例节点(带有
步骤
标签),然后使用
下一步
关系将它们按顺序链接在一起:

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
过程不返回任何内容,因此上面的查询只返回创建并链接在一起的节点数。

如果你有apoc,你可以使用
apoc.nodes.link(nodes,“NEXT”)
我更喜欢人们在apoc:)之前学习密码,但是是的apoc FTW@Christophen Willemsen谢谢,我确实有一个uuid,但我只是举个例子。这很好用,当我更需要的时候,我会研究APOC。谢谢如果你有apoc,你可以使用
apoc.nodes.link(nodes,“NEXT”)
我更喜欢人们在apoc:)之前学习密码,但是apoc FTW@Christophen Willemsen谢谢,我确实有一个uuid,但我只是举个例子。这很好用,当我更需要的时候,我会研究APOC。谢谢