Is is possible to use the value of a node property as a variable name for a relationship property?

I am trying to use the value of a node property as a variable name for a relationship property, and I haven't found any way to do it so far. Here is an example:

Let's say I have some node labels including:

(p:Person {id: #, name: "some name"})

(c:Currency {id: #, name: "currency symbol"})

(t:Transaction {id: #, amount: #}

In this case, the transaction is not linked to the currency, but ignore this for now. I want to create a relationship to show that some person transacted with another.

Assumptions:

1. c.name can be one of many currencies [USD, EUR, GBP, ... etc]

2. If person A sends multiple currencies to person B, then each currency will have its own transaction.

Now if p1 sent some amounts of USD and EUR to p2, I want to create a relationship as follows:

(p1:Person)-[TRANSACTED_WITH {USD: some amount, EUR: some amount}]->(p2:Person)

So I want the relationship to have the symbol name of a sent currency as the property name and the amount as the value of that property. There can be one or multiple currencies sent from A to B. So each relationship between two persons can have a different set of properties.

I tried the following, but it didn't work:

MERGE (p1:Person)-[TRANSACTED_WITH {c1["name"]: t1.amount}]->(p2:Person)

Is there actually any way to do that?

Property names must be literal values. You can try using apoc doIt procedure, as it will let you execution a cypher statement passed as a string. As such, you can create your cypher string with the relationship's property name substituted with the value you need.

https://neo4j.com/labs/apoc/4.2/overview/apoc.cypher/apoc.cypher.doIt/

Hi @TK36 !

As @glilienfield said, there're several APOC procedures that may help you with this. An example of this can be:

MATCH(p1:Person { id : $id1}), (t1:Transaction { id : $id2}), (c1:Currency {id : $id3}), (p2:Person { id : $id4})
with *
CALL apoc.create.relationship(p1, 'TRANSACTION',
apoc.map.fromValues([
    c1.name, t1.amount
]), p2) 
YIELD rel
RETURN rel;

Hey bennu,

I have a similar yet different problem, so maybe you could help me with that.
My query should in theory work like this:

MATCH  (n)-[x:EVALUATED_IN]->(m)<-[y:EVALUATED_IN]-(o) where x.Metric = y.Metric and x.Score > y.Score and n.ID <> o.ID
with *, (toFloat(x.Score) - toFloat(y.score)) as score
call apoc.create.relationship(n, "OVERPERFORMS", 
    apoc.map.fromValues([
        x.Metric, score, 
        "Experiment", m.ID])
    , o)
yield rel
return rel
;

But my created relationships only have the "Experiment": m.ID properties.
Do you have any idea why? (x.Metric is a valid property that every "EVALUATED_IN"-Property has)

Appreciate any ideas

I think your 'score' value is null, thus it is not added to the map. The cause is a misspelling in your formula. Note, that you have 'y.score', not 'y.Score' in the formula for 'score'.

2 Likes

Thanks, now it works. Typical mistake after trying out many different solutions and being tired. Should have had a look again a few hours later.

2 Likes