Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/neo4j/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 使用Cypher将多行收集到一列中_Neo4j_Cypher - Fatal编程技术网

Neo4j 使用Cypher将多行收集到一列中

Neo4j 使用Cypher将多行收集到一列中,neo4j,cypher,Neo4j,Cypher,我有一个高度链接的数据模型存储在neo4j中。数据大致如下: Component -> Part (only 1) \-> Fastener (only 1) 随后,带有标签零件或紧固件的任何节点都可以有任意数量的链接到其他节点(但决不能返回到组件) 我要做的是返回所有组件,其中包含一个Part列、紧固件列,一列用于该部分的连接(比如作为字典数组),另一列用于该紧固件的连接 目前,我有一个非常基本的查询,可以“工作”,但会生成同一组件的多行,其中一行由唯一的零件或

我有一个高度链接的数据模型存储在neo4j中。数据大致如下:

Component -> Part (only 1)
         \-> Fastener (only 1)
随后,带有标签零件或紧固件的任何节点都可以有任意数量的链接到其他节点(但决不能返回到组件)

我要做的是返回所有组件,其中包含一个Part列、紧固件列,一列用于该部分的连接(比如作为字典数组),另一列用于该紧固件的连接

目前,我有一个非常基本的查询,可以“工作”,但会生成同一组件的多行,其中一行由唯一的零件或紧固件连接组成。查询是:

MATCH (c:Component)-[:MADE_WITH]->(p:Part), (c)-[:MADE_WITH]->(f:Fastener), (p)-[p_m:MATERIAL]->(p_m_unk), (f)-[f_m:MATERIAL]->(f_m_unk)
RETURN c.name, p, f, p_m_unk, p_m, f_m_unk, f_m
经过一些阅读,似乎COLLECT函数将完成我需要的部分功能,但如果我这样做:

MATCH (c:Component)-[:MADE_WITH]->(p:Part), (c)-[:MADE_WITH]->(f:Fastener), (p)-[p_m:MATERIAL]->(p_m_unk), (f)-[f_m:MATERIAL]->(f_m_unk)
RETURN c.name, p, f, COLLECT([p_m_unk, p_m]), COLLECT([f_m_unk, f_m])
这并不是我想要的,因为数据较少的列(要么
p\m\u unk
要么
f\m\u unk
)将有重复的行

如何让此查询为每个
c.name
返回一行,其中包含所有零件
p
、紧固件
f
,以及它们各自的一级连接


(我已经更改了标签的实际结构和名称,使其比我的用例更通用,但数据模型和查询仍然是一样的。)

您的思路是正确的,我认为问题是您试图在一开始就进行所有匹配,生成笛卡尔积并最终在集合中创建重复项。您将希望分解匹配,分别收集数据(因此每个步骤的输出是每个组件的一行),以避免笛卡尔积

// you can still match against part and fastener together to start
MATCH (c:Component)-[:MADE_WITH]->(p:Part), (c)-[:MADE_WITH]->(f:Fastener) 
WITH c, p, f
// now match on part connections and collect
MATCH (p)-[:MATERIAL]->(p_m_unk)
WITH c, p, f, COLLECT(p_m_unk) as partConnections
// now match on fastener connections and collect
MATCH (f)-[:MATERIAL]->(f_m_unk)
// could do a return here if we wanted to
WITH c, p, f, partConnections, COLLECT(f_m_unk) as fastenerConnections
RETURN c.name, p, f, partConnections, fastenerConnections

你在正确的轨道上,我认为问题是你试图在一开始就进行所有匹配,这就是生成笛卡尔积,并最终在你的集合中创建重复项。您将希望分解匹配,分别收集数据(因此每个步骤的输出是每个组件的一行),以避免笛卡尔积

// you can still match against part and fastener together to start
MATCH (c:Component)-[:MADE_WITH]->(p:Part), (c)-[:MADE_WITH]->(f:Fastener) 
WITH c, p, f
// now match on part connections and collect
MATCH (p)-[:MATERIAL]->(p_m_unk)
WITH c, p, f, COLLECT(p_m_unk) as partConnections
// now match on fastener connections and collect
MATCH (f)-[:MATERIAL]->(f_m_unk)
// could do a return here if we wanted to
WITH c, p, f, partConnections, COLLECT(f_m_unk) as fastenerConnections
RETURN c.name, p, f, partConnections, fastenerConnections

如果每个
组件
可以返回两行,一行用于
零件
,另一行用于
紧固件
,则查询可以如此简单:

MATCH (c:Component)-[:MADE_WITH]->(pf)-[m:MATERIAL]->(unk)
RETURN c.name, LABELS(pf)[0] AS label, pf, COLLECT({m:m, unk:unk}) AS materials;
该查询假定
零件
紧固件
节点没有其他标签

以下是一个示例结果:

╒══════╤════════╤═════════════╤══════════════════════════════╕
│c.name│label   │pf           │materials                     │
╞══════╪════════╪═════════════╪══════════════════════════════╡
│Froomb│Fastener│{name: Batz} │[{m: {name: MFlidget}, unk: {n│
│      │        │             │ame: Flidget}}, {m: {name: MCo│
│      │        │             │rb}, unk: {name: Corb}}]      │
├──────┼────────┼─────────────┼──────────────────────────────┤
│Froomb│Part    │{name: Bleet}│[{m: {name: MSignaft}, unk: {n│
│      │        │             │ame: Signaft}}, {m: {name: MTr│
│      │        │             │em}, unk: {name: Trem}}, {m: {│
│      │        │             │name: MMert}, unk: {name: Mert│
│      │        │             │}}]                           │
└──────┴────────┴─────────────┴──────────────────────────────┘
但是,如果您真的在一行上为每个
组件
查询结果,则此查询将执行以下操作:

MATCH (c:Component)-[:MADE_WITH]->(pf)-[m:MATERIAL]->(unk)
WITH c.name AS name, pf, COLLECT(m) AS ms, COLLECT(unk) AS unks
ORDER BY LABELS(pf)[0] DESC
WITH name, COLLECT({pf: pf, ms:ms, unks:unks}) AS data
RETURN name, (data[0]).pf AS p, (data[1]).pf AS f, (data[0]).ms AS p_ms, (data[0]).unks AS p_m_unks, (data[1]).ms AS f_ms, (data[1]).unks AS f_m_unks;
orderby
子句根据
pf
节点的标签按降序排序,以便在
数据
集合中,
部分
数据具有索引0,
紧固件
数据具有索引1

以下是结果(使用相同的样本数据)的结果:


如果每个
组件
可以返回两行,一行用于
零件
,另一行用于
紧固件
,则查询可以如此简单:

MATCH (c:Component)-[:MADE_WITH]->(pf)-[m:MATERIAL]->(unk)
RETURN c.name, LABELS(pf)[0] AS label, pf, COLLECT({m:m, unk:unk}) AS materials;
该查询假定
零件
紧固件
节点没有其他标签

以下是一个示例结果:

╒══════╤════════╤═════════════╤══════════════════════════════╕
│c.name│label   │pf           │materials                     │
╞══════╪════════╪═════════════╪══════════════════════════════╡
│Froomb│Fastener│{name: Batz} │[{m: {name: MFlidget}, unk: {n│
│      │        │             │ame: Flidget}}, {m: {name: MCo│
│      │        │             │rb}, unk: {name: Corb}}]      │
├──────┼────────┼─────────────┼──────────────────────────────┤
│Froomb│Part    │{name: Bleet}│[{m: {name: MSignaft}, unk: {n│
│      │        │             │ame: Signaft}}, {m: {name: MTr│
│      │        │             │em}, unk: {name: Trem}}, {m: {│
│      │        │             │name: MMert}, unk: {name: Mert│
│      │        │             │}}]                           │
└──────┴────────┴─────────────┴──────────────────────────────┘
但是,如果您真的在一行上为每个
组件
查询结果,则此查询将执行以下操作:

MATCH (c:Component)-[:MADE_WITH]->(pf)-[m:MATERIAL]->(unk)
WITH c.name AS name, pf, COLLECT(m) AS ms, COLLECT(unk) AS unks
ORDER BY LABELS(pf)[0] DESC
WITH name, COLLECT({pf: pf, ms:ms, unks:unks}) AS data
RETURN name, (data[0]).pf AS p, (data[1]).pf AS f, (data[0]).ms AS p_ms, (data[0]).unks AS p_m_unks, (data[1]).ms AS f_ms, (data[1]).unks AS f_m_unks;
orderby
子句根据
pf
节点的标签按降序排序,以便在
数据
集合中,
部分
数据具有索引0,
紧固件
数据具有索引1

以下是结果(使用相同的样本数据)的结果:


您可以在
COLLECT
函数调用中使用
DISTINCT
修饰符

RETURN c.name, p, f, COLLECT(DISTINCT [p_m_unk, p_m]), COLLECT(DISTINCT [f_m_unk, f_m])

这将从较长的列表中删除重复项。

您可以在
COLLECT
函数调用中使用
DISTINCT
修饰符

RETURN c.name, p, f, COLLECT(DISTINCT [p_m_unk, p_m]), COLLECT(DISTINCT [f_m_unk, f_m])

这将从较长的列表中删除重复项。

感谢InverseFalcon和cybersam的回复!!两种解决方案都非常有效。感谢InverseFalcon和cybersam的回复!!两种解决方案都非常有效。感谢您对InverseFalcon的帮助!您的解决方案和cybersam的解决方案对我都很有效。感谢您对InverseFalcon的帮助!你的解决方案和cybersam的解决方案对我都很有效。