Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to access and mutate node property value by the property name string in Cypher?

My goal is to access and mutate a property of a node in a cypher query where the name of the property to be accessed and mutated is an unknown string value.

For example, consider a command:

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.

The particular case is easy:

MATCH ( node )
WHERE has(node.age) AND has(node.AGE) AND node.age <> node.AGE
SET node.AGE = node.age
RETURN node;

But I can't seem to find a way to implement the general case in a single request.

Specifically, I am unable to:

  1. Access the property of the node with a string and a value
  2. Mutate the property of the node with a string and a value

For the sake of clarity, I'll include my attempt to handle the general case. Where I failed to modify the property of the node I was able to generate the cypher for a command that would accomplish my end goal if it were executed in a subsequent transaction.

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)

Afterthought: It seems like the ability to mutate a node property by property name would be a pretty common requirement, but the lack of obvious support for the feature leads me to believe that the feature was omitted deliberately? If this feature is indeed unsupported is there any documentation to explain why and if there is some conflict between the approach and the recommended way of doing things in Neo/Cypher?

like image 871
smartcaveman Avatar asked May 01 '15 23:05

smartcaveman


People also ask

What Cypher clauses can you use to create a node?

The CREATE clause is used to create nodes and relationships.

How do you write a Cypher query?

Cypher uses an ASCII-art type of syntax where (nodes)-[:ARE_CONNECTED_TO]->(otherNodes) using rounded brackets for circular (nodes) , and -[:ARROWS]-> for relationships. When you write a query, you draw a graph pattern through your data.

How do I change my relationship name in Neo4j?

You cannot rename an already existing relationship. You'd have to run through all relationships, create the new one in parallel (including all properties) and then remove the old one.

WHAT IS WITH clause in Cypher?

The WITH clause allows query parts to be chained together, piping the results from one to be used as starting points or criteria in the next. It is important to note that WITH affects variables in scope.


1 Answers

There is some discussion going on regarding improved support for dynamic property access in Cypher. I'm pretty confident that we will see support for this in the future, but I cannot comment on a target release nor on a date.

As a workaround I'd recommend implementing that into a unmanaged extension.

like image 160
Stefan Armbruster Avatar answered Oct 11 '22 20:10

Stefan Armbruster