Search code examples
neo4jcyphergraph-databases

How do I set relationship data as properties on a node?


I've taken the leap from SQL to Neo4j. I have a few complicated relationships that I need to set as properties on nodes as the first step towards building a recommendation engine.

This Cypher query returns a list of categories and weights.

MATCH (m:Movie {name: "The Matrix"})<-[:TAKEN_FROM]-(i:Image)-[r:CLASSIFIED_AS]->(c:Category) RETURN c.name, avg(r.weight)

This returns

{ "fighting": 0.334, "looking moody": 0.250, "lying down": 0.237 }

How do I set these results as key value pairs on the parent node?

The desired outcome is this:

(m:Movie { "name": "The Matrix", "fighting": 0.334, "looking moody": 0.250, "lying down": 0.237 })

Also, I assume I should process my (m:Movie) nodes in batches so what is the best way of accomplishing this?


Solution

  • Not quite sure how you're getting that output, that return shouldn't be returning both of them as key value pairs. Instead I would expect something like: {"c.name":"fighting", "avg(r.weight)":0.334}, with separate records for each pair.

    You may need APOC procedures for this, as you need a means to set the property key to the value of the category name. That's a bit tricky, but you can do this by creating a map from the collected pairs, then use SET with += to update the relevant properties:

    MATCH (m:Movie {name: "The Matrix"})<-[:TAKEN_FROM]-(:Image)-[r:CLASSIFIED_AS]->(c:Category) 
    WITH m, c.name as name, avg(r.weight) as weight
    WITH m, collect([name, weight]) as category
    WITH m, apoc.map.fromPairs(category) as categories
    SET m += categories
    

    As far as batching goes, take a look at apoc.periodic.iterate(), it will allow you to iterate on the streamed results of the outer query and execute the inner query on batches of the stream:

    CALL apoc.periodic.iterate(
     "MATCH (m:Movie)
     RETURN m",
     "MATCH (m)<-[:TAKEN_FROM]-(:Image)-[r:CLASSIFIED_AS]->(c:Category) 
      WITH m, c.name as name, avg(r.weight) as weight
      WITH m, collect([name, weight]) as category
      WITH m, apoc.map.fromPairs(category) as categories
      SET m += categories",
    {iterateList:true, parallel:false}) YIELD total, batches, errorMessages
    RETURN total, batches, errorMessages