[英]How can I use neo4j cypher query to create a histogram of nodes bucketed by number of relationships?
[英]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.