如何通过 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;

但我似乎找不到在单个请求中实现一般情况的方法。

具体来说,我无法:

  1. 用字符串和值
  2. 访问节点的属性
  3. 用一个字符串和一个值
  4. 改变节点的属性

为了清楚起见,我将包括我对处理一般情况的尝试。在我未能修改节点的 属性 的地方,我能够为一个命令生成密码,如果它在后续事务中执行,该命令将实现我的最终目标。

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 团队!