如何通过 Cypher 中的 属性 名称字符串访问和改变节点 属性 的值?
How to access and mutate node property value by the property name string in Cypher?
我的目标是在密码查询中访问和改变节点的属性,其中要访问和改变属性的名称是一个未知的字符串值。
例如,考虑一个命令:
Find all nodes containing a two properties such that the name of the first property is lower-case and the name of the latter is the upper-case representation of the former. Then, propagate the value of the property with the lower-case string name to the value of the property with the upper-case name.
具体情况很简单:
MATCH ( node )
WHERE has(node.age) AND has(node.AGE) AND node.age <> node.AGE
SET node.AGE = node.age
RETURN node;
但我似乎找不到在单个请求中实现一般情况的方法。
具体来说,我无法:
- 用字符串和值
访问节点的属性
- 用一个字符串和一个值
改变节点的属性
为了清楚起见,我将包括我对处理一般情况的尝试。在我未能修改节点的 属性 的地方,我能够为一个命令生成密码,如果它在后续事务中执行,该命令将实现我的最终目标。
MERGE ( justToMakeSureOneExists { age: 14, AGE : 140 } ) WITH justToMakeSureOneExists
MATCH (node)
WHERE ANY ( kx IN keys(node) WHERE kx = LOWER(kx) AND ANY ( ky in keys(node) WHERE ky = UPPER(kx) ) )
REMOVE node.name_conflicts // make sure results are current
FOREACH(kx in keys(node) |
SET node.name_conflicts
= COALESCE(node.name_conflicts,[])
+ CASE kx
WHEN lower(kx)
THEN []
+ CASE WHEN any ( ky in keys(node) WHERE ky = upper(kx) )
THEN ['match (node) where id(node) = ' + id(node)+ ' and node.' + upper(kx) + ' <> node.' + kx + ' set node.' + upper(kx) + ' = node.' + kx + ' return node;']
ELSE [] END
ELSE []
END )
RETURN node,keys(node)
事后思考: 似乎能够通过 属性 名称对节点 属性 进行变异是一个非常普遍的要求,但缺乏明显的对该功能的支持使我相信该功能是故意省略的?如果此功能确实不受支持,是否有任何文档可以解释原因以及该方法与 Neo/Cypher 中推荐的做事方式之间是否存在冲突?
关于改进对 Cypher 中动态 属性 访问的支持的讨论正在进行中。我非常有信心我们将来会看到对此的支持,但我无法对目标版本或日期发表评论。
作为解决方法,我建议将其实施到 unmanaged extension 中。
似乎所需的语言功能已添加到 Neo4j 2.3.0 中的 Cypher,名称为 "dynamic property"。版本 2.3.0 的 Cypher 文档将以下语法组声明为有效的密码表达式:
A dynamic property: n["prop"]
, rel[n.city + n.zip]
, map[coll[0]]
.
此功能记录在 2.3.0 but is absent from the previous version (2.2.9)。
谢谢 Neo4j 团队!
我的目标是在密码查询中访问和改变节点的属性,其中要访问和改变属性的名称是一个未知的字符串值。
例如,考虑一个命令:
Find all nodes containing a two properties such that the name of the first property is lower-case and the name of the latter is the upper-case representation of the former. Then, propagate the value of the property with the lower-case string name to the value of the property with the upper-case name.
具体情况很简单:
MATCH ( node )
WHERE has(node.age) AND has(node.AGE) AND node.age <> node.AGE
SET node.AGE = node.age
RETURN node;
但我似乎找不到在单个请求中实现一般情况的方法。
具体来说,我无法:
- 用字符串和值 访问节点的属性
- 用一个字符串和一个值 改变节点的属性
为了清楚起见,我将包括我对处理一般情况的尝试。在我未能修改节点的 属性 的地方,我能够为一个命令生成密码,如果它在后续事务中执行,该命令将实现我的最终目标。
MERGE ( justToMakeSureOneExists { age: 14, AGE : 140 } ) WITH justToMakeSureOneExists
MATCH (node)
WHERE ANY ( kx IN keys(node) WHERE kx = LOWER(kx) AND ANY ( ky in keys(node) WHERE ky = UPPER(kx) ) )
REMOVE node.name_conflicts // make sure results are current
FOREACH(kx in keys(node) |
SET node.name_conflicts
= COALESCE(node.name_conflicts,[])
+ CASE kx
WHEN lower(kx)
THEN []
+ CASE WHEN any ( ky in keys(node) WHERE ky = upper(kx) )
THEN ['match (node) where id(node) = ' + id(node)+ ' and node.' + upper(kx) + ' <> node.' + kx + ' set node.' + upper(kx) + ' = node.' + kx + ' return node;']
ELSE [] END
ELSE []
END )
RETURN node,keys(node)
事后思考: 似乎能够通过 属性 名称对节点 属性 进行变异是一个非常普遍的要求,但缺乏明显的对该功能的支持使我相信该功能是故意省略的?如果此功能确实不受支持,是否有任何文档可以解释原因以及该方法与 Neo/Cypher 中推荐的做事方式之间是否存在冲突?
关于改进对 Cypher 中动态 属性 访问的支持的讨论正在进行中。我非常有信心我们将来会看到对此的支持,但我无法对目标版本或日期发表评论。
作为解决方法,我建议将其实施到 unmanaged extension 中。
似乎所需的语言功能已添加到 Neo4j 2.3.0 中的 Cypher,名称为 "dynamic property"。版本 2.3.0 的 Cypher 文档将以下语法组声明为有效的密码表达式:
A dynamic property:
n["prop"]
,rel[n.city + n.zip]
,map[coll[0]]
.
此功能记录在 2.3.0 but is absent from the previous version (2.2.9)。
谢谢 Neo4j 团队!