cancel
Showing results for 
Search instead for 
Did you mean: 

Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.

How to form a graph DB from relation object

I wrote a python code which will extract meaningful relation from a given text as an input.

Please check the below image for better understanding

Jupyter123_0-1671519287785.png

The above image show that, I extracted the relation from the text

Now i want to move those relation object to neo4j and form a graph?

how do i do that? what is the query for that?

2 ACCEPTED SOLUTIONS

The json file consists of a single json object with key 'relations', whose value is an array. As such, @Estelle query need to be modified to account for that. Try the following: 

CALL apoc.load.json("file:///sample.json") YIELD value
UNWIND value.relations as relation
MERGE (head:Entity {name: relation.head})
MERGE (tail:Entity {name: relation.tail})
WITH head, relation, tail, toUpper(replace(relation.type, " ", "_")) as type
CALL apoc.create.relationship(head, type, {}, tail) YIELD rel
RETURN count(rel)

I replaced the relationship values to conform to best practices. Also, the 'meta' value is a json map, which can not be saved as a relationship property. Is there data in 'meta' that you want to save? 

View solution in original post

Try this:

MERGE(main:Entity{name:'main'})
WITH main
CALL apoc.load.json("file:///sample.json") YIELD value
UNWIND value.relations as relation
MERGE (head:Entity {name: relation.head})
MERGE (tail:Entity {name: relation.tail})
MERGE (head)-[:HAS_MAIN]->(main)
WITH head, relation, tail, toUpper(replace(relation.type, " ", "_")) as type
CALL apoc.create.relationship(head, type, {}, tail) YIELD rel
RETURN count(rel)

Screen Shot 2022-12-26 at 10.42.57 AM.png 

There are only 15 relationships incoming to the main node. This is because your data only has 15 distinct head nodes. 

Screen Shot 2022-12-26 at 10.44.39 AM.png

View solution in original post

24 REPLIES 24

Hello,

You can save your result as JSON and import it with APOC: apoc.load.json (https://neo4j.com/labs/apoc/4.4/overview/apoc.load/apoc.load.json/)

Not tested, but query could look like this:

CALL apoc.load.json("path/to/file.json") YIELD value
MERGE (head:Entity {name: value.head})
MERGE (tail:Entity {name: value.tail})
CALL apoc.create.relationship(head, value.type, value.meta, tail) YIELD rel
RETURN count(rel)

Explantions:

  • "get or create" the head entity whose name is the head value is the JSON
  • Same for the tail entity
    NOTE: if entities are already in the database, just use MATCH instead of MERGE
  • Then, create the relationship between entities, using apoc.create.relationship to create a relationship with dynamic type (https://neo4j.com/labs/apoc/4.4/overview/apoc.create/apoc.create.relationship/)
  • In the end, just return the number of created relationships. Up to you to decide what you want to see in the end, if you want to see something

 

Jupyter123_0-1671534233599.png

 @Estelle Hi, im getting this error.

 

Its because you have an extra 'with' clause at the end of the first line. You need to put the 'with' between the 'merge' and 'call' on line 3. 

WITH head, value, tail

Jupyter123
Node Clone

hi @Estelle , thanks for the response.

Well, Instead of converting the object to JSON 

Is it possible to do this via python object?

Pls note that: I already connected python code and neo4j by this command:

from neo4j import GraphDatabase

data_base_connection1 = GraphDatabase.driver(uri = "bolt://localhost:7687", auth=("neo4j", "password"))
session1 = data_base_connection1.session()

In my python program i have a class called KB and inside that class i have a method called def print(self): and some logic inside that..

So whenever i type KB.print()

i get relation object [ the one that i shown in above image]

so what would be the query to send that relation object from python to neo4j and form a graph?

 

Sure you can also do that. In your KB class you can probably have a method returning dictionnaries, then the dict keys are used as variables in the query you execute with the driver, something like:

query = """
MERGE (head:Entity {name: $head})
MERGE (tail:Entity {name: $tail})
CALL apoc.create.relationship(head, $type, $meta, tail) YIELD rel
RETURN count(rel)
"""
params = {
   "head": "",
   "type": "",
   "tail": "",
   "meta": {}
}
with driver.session() as s:
   s.run(query, params)

@Estelle hi there, the query seems to be showing many errors like...

in-between merge and call 'with' should come.

could you please test the query and let me know 

Hi @Jupyter123 ,

The error message seems quite explicit, what have you tried to fix the query and what is your problem?

hey @Estelle 

I have uploaded JSON file in the below link. Please have a look

https://easyupload.io/y7ne07

I want that JSON data to be displayed in neo4j graph DB with nodes and edges

What is the query for that? 

Could you try to test that JSON file in neo4j and let me know if it's displaying in neo4j as graph?

I want the result to be like this

Jupyter123_0-1671619816743.png

 

 

The json file consists of a single json object with key 'relations', whose value is an array. As such, @Estelle query need to be modified to account for that. Try the following: 

CALL apoc.load.json("file:///sample.json") YIELD value
UNWIND value.relations as relation
MERGE (head:Entity {name: relation.head})
MERGE (tail:Entity {name: relation.tail})
WITH head, relation, tail, toUpper(replace(relation.type, " ", "_")) as type
CALL apoc.create.relationship(head, type, {}, tail) YIELD rel
RETURN count(rel)

I replaced the relationship values to conform to best practices. Also, the 'meta' value is a json map, which can not be saved as a relationship property. Is there data in 'meta' that you want to save? 

hi there @glilienfield @Estelle 
i dont want the meta value

i just want the 'head' node, 'tail' node and 'type' relation and that should form a graph.

by the way, i executed your code and i get like this.
please see below image

Jupyter123_0-1671636647305.png

still i haven't got any graph though.

 

You did not attach your image.  This is what I got:

Screen Shot 2022-12-21 at 10.33.51 AM.png

i edited it, pls check the image and it's nice you have got my expected graph.

Could you check what's the error i did tho?

Interesting.  I got 23 relationships. What does the output look like when you execute: 

CALL apoc.load.json("file:///sample.json") YIELD value
return value

 

@glilienfield the output look like this 

Jupyter123_0-1671637863033.png

 

i dont see any nodes getting created

Ok, that structure is different from what you posted. That data looks to be an array. It is not a value of the 'relation' key, as was in the file you posted. That would explain the issue. Can you post the final json file? I can modify the query. 

hi @glilienfield , morning.

oh yeah i just checked, i used different wrong json structure. 

let me use the one which i sent you and will update you

hey @glilienfield 

just a small help

can you modify the same query in such a way where there should be a top node among all these nodes and that top node should connect every head node.

top node should be named as 'main' and that 'main' top node should relate with every other head node .

pls note that: top node is not in json file.

json file has head node, tail node and type(relation)

i want to create a single top node and that top node should match all head nodes..

what's the query for that? 

something like this

Jupyter123_0-1672050735285.png

 

Is this a main node for each json imported, if so, how will you differentiate each main node?  Will you use a unique ‘id’ or ‘name’ property?  

@glilienfield hi there

There is only one json file and not more than one json.

You can use the existing json itself, and want to create a main node ( top node) named as main. And that top node should connect with each head node in that json file.

I hope it's clear 

Try this:

MERGE(main:Entity{name:'main'})
WITH main
CALL apoc.load.json("file:///sample.json") YIELD value
UNWIND value.relations as relation
MERGE (head:Entity {name: relation.head})
MERGE (tail:Entity {name: relation.tail})
MERGE (head)-[:HAS_MAIN]->(main)
WITH head, relation, tail, toUpper(replace(relation.type, " ", "_")) as type
CALL apoc.create.relationship(head, type, {}, tail) YIELD rel
RETURN count(rel)

Screen Shot 2022-12-26 at 10.42.57 AM.png 

There are only 15 relationships incoming to the main node. This is because your data only has 15 distinct head nodes. 

Screen Shot 2022-12-26 at 10.44.39 AM.png

cheers @Estelle as expected. i really appreciate your time and patience for helping me out.

+1 kudos to you..

@glilienfield thank you very much! it worked!

 

@glilienfield i saw your graph, it's close to my expected output.
just one quick change, instead of displaying node as numbers, can you display as corresponding to head and tail name in json?

something like this

Jupyter123_0-1671637337614.png

 

@glilienfield 

hey mate, its working now

my bad , earlier i had wrong JSON file.

Now i updated json and it works.

Jupyter123_0-1671681774130.png

thank you very much