TUrwin
TUrwin

Reputation: 825

How can I assign a node property value to a variable in Cypher?

We're trying to propagate a property on nodes with a specific label ("Concept") to connected nodes (with predicate "CONTAINS_OBJECT") as a new label, but are struggling to assign the property to a variable within the query. How can this be done assuming there will be multiple "Concept" nodes, with the assumption that no "Concept" nodes will have overlapping connections with other "Concept" nodes.

i.e. The following will never occur, where n0 and n1 are distinct:

(n0:Concept)-[:CONTAINS_OBJECT]->(o:Object)<-[:CONTAINS_OBJECT]-(n1:Concept)

Basically, how should this be done with Cypher?

Disclaimer: We're quite new to Cypher - any and all advice is appreciated.

We have tried a few more restricted queries but have had issues getting variable assignment working there as well.

This query achieved the desired result for a single specified "Concept" node:

    MATCH p = (c:Concept{ Name: 'Con0' })-[:CONTAINS_OBJECT]->(END)
    FOREACH (n in nodes(p) | SET n:Con0)

The following query was our attempt to bind the "Concept" node's 'Name' property to a variable", but 'p' isn't being assigned in this instance:

    MATCH p = (c:Concept{ Name: 'Con0' })-[:CONTAINS_OBJECT]->(END)
    WITH c.Name as conceptName
    FOREACH (n in nodes(p) | SET n:conceptName)

To simplify the result we're after as much as possible, the end result is that the following two MATCH statements should return the same results for any given "Concept" node:

1)

    MATCH (c:Concept{ Name: 'Con0' })-[:CONTAINS_OBJECT]->(o:Object)

2)

    MATCH (c:Concept{ Name: 'Con0' })-[:CONTAINS_OBJECT]->(o:Con0)

Looking to build a query along these lines:

    MATCH p = (c:Concept)-[:CONTAINS_OBJECT]->(END)
    WITH c.Name as conceptName
    FOREACH (n in nodes(p) | SET n:conceptName)

Upvotes: 0

Views: 942

Answers (2)

TUrwin
TUrwin

Reputation: 825

For anyone that comes to this post with similar requirements, we eventually came to the following query which got us exactly the result we were after:

call apoc.periodic.commit("MATCH (n:Concept)-[:CONTAINS_OBJECT]->(o:Object)
    WITH o, n, replace(n.Name, ' ', '_') as label limit {limit} call
    apoc.create.addLabels(o, [label]) yield node
    with node
    RETURN node",
{limit:100000});

Note that we have < 150 nodes labelled with "Concept", and had 'Name' fields containing spaces which we've replaced with underscores.

Upvotes: 0

cybersam
cybersam

Reputation: 67044

I'm having a hard time understanding your question, as it is using some neo4j terminology in nonstandard ways. For example, your Cypher code uses CONTAINS_OBJECT as a "relationship type" - not a "predicate" or "label". On the other hand, it does use Concept as a "label" (a term that only applies to nodes).

If you are asking how to copy labels between specific nodes, the answer is that you cannot do that in the Cypher language itself (unless you know beforehand the entire set of labels that could be used). This is because the raw Cypher language does not support assigning labels using a variable.

However, you can call the APOC procedure apoc.create.addLabels (after installing the APOC plugin) to copy all the labels from one node to another. For instance, this query copies all the labels from the c node to the obj node:

MATCH (c:Concept)-[:CONTAINS_OBJECT]->(obj)
CALL apoc.create.addLabels(obj, LABELS(c)) YIELD node
RETURN node

Upvotes: 2

Related Questions