Search code examples
graphneo4jcypher

Miss Relationship Using Cypher Query in Neo4j


I am working on Cypher query using UNWIND and Foreach in Neo4j. I am sure there is a bug, but I cannot figure out where I did wrong.

I am building a graph with three spans in a trace as follows (in "test.json")

   [
    {
        "spanId":"3",
        "name": "checkOut",
        "parentId": ["1"],
        "service_name": "svc"
    },
    {
        "spanId":"2",
        "name": "addCart",
        "parentId": ["1"],
        "service_name": "svc"
    },
    {
        "spanId":"1",
        "name": "frontend",
        "service_name": "svc"
    }
]

Span checkOut and addCart are child of front, so there are parent-child relationships between frontend -> checkOut and frontend -> addCart.

Meanwhile, these spans all belong to "svc" service, so they should have relationship to "svc". However, frontend misses the relation to "svc". See below

enter image description here

My Cypher query is as follows:

WITH 'file:///test.json' AS url

CALL apoc.load.json(url) YIELD value

MERGE (s:Span {span_id: value.spanId})
ON CREATE SET  s.name=value.name, s.service=value.service_name

WITH s, value
UNWIND value.parentId AS parent
MERGE (p:Span {span_id: parent})
MERGE (p)-[:PARENT_OF]->(s)

WITH s, value, value.service_name AS ki
FOREACH(k IN ki | 
     MERGE (svc:Service{service: value.service_name} )
     MERGE (s)-[:FROM_SERVICE]->(svc)
)

Can someone help me see where I did wrong in the Cypher query? A ton of thanks!


Solution

  • The problem is in the UNWIND statement, your frontend object doesn't have a parentId array, so there is nothing to unwind there and the object gets lost, before creating a relationship to service. To fix this, you should move the creation and merge of relationship with service above UNWIND. Try this:

    WITH 'file:///test.json' AS url
    CALL apoc.load.json(url) YIELD value
    MERGE (s:Span {span_id: value.spanId})
    ON CREATE SET  s.name=value.name, s.service=value.service_name
    WITH s, value, value.service_name AS ki
    FOREACH(k IN ki | 
         MERGE (svc:Service{service: value.service_name} )
         MERGE (s)-[:FROM_SERVICE]->(svc)
    )
    UNWIND value.parentId AS parent
    MERGE (p:Span {span_id: parent})
    MERGE (p)-[:PARENT_OF]->(s)