Neo4j/CYPHER: 如何高效地从节点、关系和目标节点查询某些属性?
Neo4j/CYPHER: How can I query some properties from a node, its relationships and target node efficiently?
我想查询一组节点的属性子集、它们的关系以及具有某些属性的目标节点(来自 Java 通过 REST 使用 CYPHER)。我的想法如下:
MATCH a WHERE id(a) IN {ids}
OPTIONAL MATCH (a)-[r]->(b)
RETURN id(a), a.name, a.attr1, r.attr2, id(b), b.name
现在我得到每个关系的 "row",但它多次包含每个节点的数据 "a"。
有没有更好的方法来进行这样的查询,以便节点 "a" 的属性只传输一次?一种思路是做2个单独的查询,但是如果WHERE条件稍微复杂一点,可能会执行两次。
使用收集功能。
http://neo4j.com/docs/stable/query-aggregation.html#aggregation-collect
MATCH a WHERE id(a) IN {ids}
OPTIONAL MATCH (a)-[r]->(b)
RETURN id(a), a.name, a.attr1, collect([r.attr2, id(b), b.name])
@frant.hartm的回答完全正确!但是,如果您想使用稍微不同的方法,您可以考虑以下方法:
想象下图:
create
(p1:Employee {name:"John"})-[:works_at]->(e1:Employer {name:"Microsoft"}),
(p1)-[:works_at]->(e2:Employer {name:"Oracle"}),
(p2:Employee {name:"Jim"})-[:works_at]->(e1),
(p2)-[:works_at]->(e2)
return p1, p2, e1, e2
// RESULT:
// (Jim)-works_at->(Microsoft)
// (Jim)-works_at->(Oracle)
// (John)-works_at->(Microsoft)
// (John)-works_at->(Oracle)
为了 COLLECT
获得良好的输出格式,您还可以使用 文字映射 ,如下例所示:
MATCH
(a:Employee)-[r:works_at]->(e:Employer)
WITH
a,
r,
COLLECT({name:e.name, id:ID(e)}) AS employers
WITH
a,
COLLECT({ type : type(r), employers : employers}) AS employerRels
WITH
{ name : a.name, id: ID(a), employers : employerRels} AS employee
RETURN
employee
然后,很棒的结果将很好地格式化 JSON 像这样:
{
"name": "Jim",
"id": 227,
"employers": [
{
"type": "works_at",
"employers": [
{
"name": "Oracle",
"id": 226
}
]
},
{
"type": "works_at",
"employers": [
{
"name": "Microsoft",
"id": 225
}
]
}
]
},
{
"name": "John",
"id": 224,
"employers": [
{
"type": "works_at",
"employers": [
{
"name": "Oracle",
"id": 226
}
]
},
{
"type": "works_at",
"employers": [
{
"name": "Microsoft",
"id": 225
}
]
}
]
}
我想查询一组节点的属性子集、它们的关系以及具有某些属性的目标节点(来自 Java 通过 REST 使用 CYPHER)。我的想法如下:
MATCH a WHERE id(a) IN {ids}
OPTIONAL MATCH (a)-[r]->(b)
RETURN id(a), a.name, a.attr1, r.attr2, id(b), b.name
现在我得到每个关系的 "row",但它多次包含每个节点的数据 "a"。
有没有更好的方法来进行这样的查询,以便节点 "a" 的属性只传输一次?一种思路是做2个单独的查询,但是如果WHERE条件稍微复杂一点,可能会执行两次。
使用收集功能。
http://neo4j.com/docs/stable/query-aggregation.html#aggregation-collect
MATCH a WHERE id(a) IN {ids}
OPTIONAL MATCH (a)-[r]->(b)
RETURN id(a), a.name, a.attr1, collect([r.attr2, id(b), b.name])
@frant.hartm的回答完全正确!但是,如果您想使用稍微不同的方法,您可以考虑以下方法:
想象下图:
create
(p1:Employee {name:"John"})-[:works_at]->(e1:Employer {name:"Microsoft"}),
(p1)-[:works_at]->(e2:Employer {name:"Oracle"}),
(p2:Employee {name:"Jim"})-[:works_at]->(e1),
(p2)-[:works_at]->(e2)
return p1, p2, e1, e2
// RESULT:
// (Jim)-works_at->(Microsoft)
// (Jim)-works_at->(Oracle)
// (John)-works_at->(Microsoft)
// (John)-works_at->(Oracle)
为了 COLLECT
获得良好的输出格式,您还可以使用 文字映射 ,如下例所示:
MATCH
(a:Employee)-[r:works_at]->(e:Employer)
WITH
a,
r,
COLLECT({name:e.name, id:ID(e)}) AS employers
WITH
a,
COLLECT({ type : type(r), employers : employers}) AS employerRels
WITH
{ name : a.name, id: ID(a), employers : employerRels} AS employee
RETURN
employee
然后,很棒的结果将很好地格式化 JSON 像这样:
{
"name": "Jim",
"id": 227,
"employers": [
{
"type": "works_at",
"employers": [
{
"name": "Oracle",
"id": 226
}
]
},
{
"type": "works_at",
"employers": [
{
"name": "Microsoft",
"id": 225
}
]
}
]
},
{
"name": "John",
"id": 224,
"employers": [
{
"type": "works_at",
"employers": [
{
"name": "Oracle",
"id": 226
}
]
},
{
"type": "works_at",
"employers": [
{
"name": "Microsoft",
"id": 225
}
]
}
]
}