cancel
Showing results for 
Search instead for 
Did you mean: 

Class Dependency Data Structure

andy_mcshane
Node Clone

Hi, I am very new to Neo4j and have followed as many tutorials as I can make sense of but I am stuck with what i am actually trying to do and I am wondering if it is because of the data structure that I am working wth. I have a JSON file that contains data for class dependencies, not a deeply nested format, a snippet of which looks like this

[
{
"id": 1,
"name": "ER00",
"isroot": false,
"isabstract": false,
"isUsedBy": ,
"dependsOn": [
{
"id": 2,
"name": "ERScheme",
"isroot": false,
"isabstract": false,
"isUsedBy": ,
"dependsOn":
}
]
},
{
"id": 2,
"name": "ERScheme",
"isroot": false,
"isabstract": false,
"isUsedBy": [
{
"id": 1,
"name": "ER00",
"isroot": false,
"isabstract": false,
"isUsedBy": ,
"dependsOn":
},
],
"dependsOn":
}
]

I am using this cypher to load the JSON and create the database.

MATCH (n) DETACH DELETE n;
//Basic Load
:param url => "file:///Dependencies_Tree_Full_UnSorted.json";

call apoc.load.json($url) yield value
//return value
unwind value as n
merge (e:Entity {name: n.name})
set e.entityId = value.id

with e, n

unwind n.dependsOn as depOn
unwind n.isUsedBy as usdBy
merge (d:Dependant {name: depOn.name})
set d.entityId = depOn.id
merge (u:UsedBy {name: usdBy.name})
set u.entityId = usdBy.id

merge (d)-[:Depends_On]-(e)
merge (e)-[:Used_By]-(u)

This does not seem to create the graph and relationships as I would expect. For example if I use this query

> match (e:Entity)-[:Depends_On]-(d:Dependant) where e.name = "ERScheme" return e,d

then I dont get the expected result. I would expect to see 'ER00' and 'ERScheme' returned but I get nothing. I must be missing something simple, any pointers please?

***** EDIT ******
I have now try changing my incoming data structure to have the following format

{
  "nodes": [
    {
      "id": 1,
      "text": "BankAccount",
      "isroot": false,
      "children": [
        {
          "id": 2,
          "text": "AccountType",
          "isroot": false,
          "children": []
        },
        {
          "id": 145,
          "text": "Branch",
          "isroot": false,
          "children": []
        },
        {
          "id": 146,
          "text": "BranchContact",
          "isroot": false,
          "children": []
        },
        {
          "id": 185,
          "text": "ChequeBookHeldBy",
          "isroot": false,
          "children": []
        },
        {
          "id": 299,
          "text": "Group",
          "isroot": false,
          "children": []
        },
        {
          "id": 176,
          "text": "Member",
          "isroot": false,
          "children": []
        },
        {
          "id": 401,
          "text": "MessageSchemaEntity",
          "isroot": false,
          "children": []
        },
        {
          "id": 167,
          "text": "SchemeRelation",
          "isroot": false,
          "children": []
        },
        {
          "id": 357,
          "text": "SchemeSSAS",
          "isroot": false,
          "children": []
        }
      ]
    },
    {
      "id": 2,
      "text": "AccountType",
      "isroot": false,
      "children": [
        {
          "id": 401,
          "text": "MessageSchemaEntity",
          "isroot": false,
          "children": []
        }
      ]
    },
  ],
  "links": [
    {
      "source": 2,
      "target": 1,
      "sourcetext": "AccountType",
      "targettext": "BankAccount"
    },
    {
      "source": 145,
      "target": 1,
      "sourcetext": "Branch",
      "targettext": "BankAccount"
    }
  ]
}

I am still strugling as to how to import this data and create the relationships between 'nodes' and 'links'. My first attempt at loading takes an absolute age to load and then when complete but does not have the relationships specified

MATCH (n) DETACH DELETE n;
//Basic Load
:param url => "file:///Dependencies_Force_Direct.json";

call apoc.load.json($url) yield value 
//return value
unwind value.nodes as nd

merge (n:Node {name: nd.text, nodeId: nd.id})

with value, n
unwind value.links as links
//merge (l:Link {name: lk.sourcetext, nodeId: lk.source})
foreach (lk in links |
	//merge (l:Link {name: lk.sourcetext, nodeId: lk.source})
    //merge (lk.sourcetext)[:Depends_On]-(lk.targettext)
    //merge (lk.targettext)[:Used_By]-(lk.sourcetext)
    merge (s:Source {name: lk.sourcetext})
    merge (t:Target {name: lk.targettext})
)

And hen I do try to specify the relationships I am getting an error stating 's' is not defined

MATCH (n) DETACH DELETE n;
//Basic Load
:param url => "file:///Dependencies_Force_Direct.json";

call apoc.load.json($url) yield value 
//return value
unwind value.nodes as nd

merge (n:Node {name: nd.text, nodeId: nd.id})

with value, n
unwind value.links as links
//merge (l:Link {name: lk.sourcetext, nodeId: lk.source})
foreach (lk in links |
	//merge (l:Link {name: lk.sourcetext, nodeId: lk.source})
    //merge (lk.sourcetext)[:Depends_On]-(lk.targettext)
    //merge (lk.targettext)[:Used_By]-(lk.sourcetext)
    merge (s:Source {name: lk.sourcetext})
    merge (t:Target {name: lk.targettext})
)
with n, s, t
merge (n)-[:Depends_On]-(s)
merge (n)-[:Used_By]->(t)

I am getting so confused!

2 REPLIES 2

You probably didn't create a constraint on Node(nodeId)

you should also only merge on the id field and set the name separately
your first unwind increases the cardinality to the number of nodes

so you want to use WITH distinct value

call apoc.load.json($url) yield value 
unwind value.nodes as nd

merge (n:Node {nodeId: nd.id})
ON CREATE SET n.name = nd.text
// reduce cardinality 
with distinct value
unwind value.links as links
// find source and target node
match (n1:Node  {nodeId: lk.source})
match (n2:Node {nodeId: lk.target})
// create relationship (one direction is enough, 2 relationships are waste
merge (n1)-[:Depends_On]->(n2)

andy_mcshane
Node Clone

Excellent, thank you, this has got me going again. I have other questions now but I will make a separate post so as not to hijack this one.