是否可以向neo4j节点添加临时属性以仅返回?

时间:2017-08-23 10:31:57

标签: neo4j cypher

我一直在使用cypher和neo4j一段时间了,我一次又一次地遇到类似的问题。

我希望能够将“临时”属性添加到仅存在于返回数据中的节点,并且不会持久保存到Neo4j数据库。

例如我正在处理的当前问题在图数据库中给出了一个N-ary树结构,我想返回一个特定节点的子节点,以及一个信息布尔让我知道那些孩子有孩子的天气。

获取此信息的查询非常简单:

MATCH (parent:Item { guid: "Identifier here" })-[:HASCHILD]->(child:Item)
OPTIONAL MATCH (child)-[:HASCHILD]->(grandchild:Item)
WITH parent, child, LENGTH(COLLECT(grandchild)) > 0 AS has_children

现在我有父母,孩子和布尔让我知道天气还有更多的孩子。

我希望接下来要做的是将has_children布尔值设置为子节点上的属性,但只是为了返回查询,我不需要该属性保持不变。

我知道有一些解决方案可以获得我想要的东西,但它们都不是我想要的。

1)我可以创建一个临时节点:(继续上面的查询)

...
WITH parent, child, LENGTH(COLLECT(grandchild)) > 0 AS haschildren,
{
    childkey1: child.childkey1,
    childkey2: child.childkey2,
    ...
    has_children: haschildren
} AS tempnode
RETURN parent, tempnode

这个解决方案不是很好,你必须知道你正在处理的节点的确切节点类型和所有属性,它在一般情况下不起作用。

2)我可以设置并删除布尔值,暂时将其保存到数据库中(如Neo4J create temp variable within Cypher中所述)。

这不是很好,因为它会导致多个数据库写入(用于添加和删除)。 此外,它不像选项1那样动态,因为它只能处理简单类型。 (选项1可以处理更复杂的情况,例如添加节点集合而不是简单的布尔值)。

据我所知,这些是临时返回数据的唯一选择。我想知道我错过了什么吗?是否有可能使这更简单或更动态?

的内容
 WITH parent, child, LENGTH(COLLECT(grandchild)) > 0 AS haschildren,
 TEMPSET child.has_children = haschildren

请注意我已经简化了一些示例。 我在neo4j中的不同上下文中多次遇到过这个问题。大多数情况下,我要么使用选项1,要么在查询返回后通过应用程序端的后处理构建正确的结构。

有更好的方法吗?

2 个答案:

答案 0 :(得分:18)

您可以尝试返回map projection。看看这个例子:

// Creating a sample node    
CREATE (:Person {name:'Jon', id: 1})

使用额外的布尔值返回投影:

MATCH (p:Person {id:1})
WITH p, true AS has_children
RETURN p{.*, has_children:has_children}

结果:

╒═════════════════════════════════════════╕
│"p"                                      │
╞═════════════════════════════════════════╡
│{"id":1,"name":"Jon","has_children":true}│
└─────────────────────────────────────────┘

上面的查询返回p节点的所有属性,带有一个额外的布尔值。

答案 1 :(得分:0)

APOC库提供的虚拟节点也可能对此有用,特别是如果您需要保留(或以其他方式映射)要向其添加属性的节点的关系时。

另请参见https://neo4j.com/docs/labs/apoc/current/virtual/https://community.neo4j.com/t/virtual-nodes-and-relationships-use-case/110。有关Apoc的安装等信息,请参见https://neo4j.com/docs/labs/apoc/current/introduction/

基本上,您要创建要向其添加属性的节点的临时(虚拟)副本,以及将这些属性连接到现有或其他虚拟节点的临时(虚拟)关系。

例如在用户->团队关系中,我们可以为用户添加一个新属性,并为这样的关系添加一个计数(已通过Neo4j v3.5测试):

MATCH (user:User)-[r:MEMBER_OF]-(team:Team)
WITH user, r, team, count(*) AS count
CALL apoc.create.vNode(labels(user), user{.*, something:'new'})
    YIELD node AS vUser
CALL apoc.create.vRelationship(vUser, type(r), r{.*,count}, team)
    YIELD rel AS vr
RETURN vUser, team, vr

或者以您的示例为例(未经测试):

MATCH (parent:Item { guid: "Identifier here" })-[r:HASCHILD]->(child:Item)
OPTIONAL MATCH (child)-[:HASCHILD]->(grandchild:Item)
WITH parent, child, LENGTH(COLLECT(grandchild)) > 0 AS has_children
CALL apoc.create.vNode(labels(child), child{.*, has_children:has_children})
    YIELD node AS vChild
CALL apoc.create.vRelationship(parent, type(r), r{.*}, vChild)
    YIELD rel AS vr
RETURN parent, vChild, vr