Can we merge multiple Nodes based on Single common property

cypher

(Groverjatin17) #1

Hi All,

I am relatively new to neo4j and I am working on 1 Use case where we are trying to merge all nodes(with 1 common property, such as all nodes with year= "1995") into 1 node where all the relationships are heading towards it rather than 3 different nodes.

For example:-
I have 3 csv files with below type of data.

Actor.csv:-

Actor Id Name
1 Sam

Movie.csv:-

Movie Id Movie Name Year Actor Id Director Id
45 Avengers 2016 1 10
23 Movie 2 2016 1 10
12 Movie 3 2016 1 10

Director.csv:-

Director ID Director Name
10 Danny Morgan

Now if I use the following Cypher Query:-

Match (actor:Actor)-[:ACTED_IN]->(movie:Movie)<-[:DIRECTED_BY]-(director:Director)
return actor, movie, director

Now the graph that appears have 1 node of actor and 3 nodes of movie then 1 node of director.
all connected via relationships.

I want there to be only 1 node of movie displaying "2016" as year and 3 edges/relationships going out of actor to the movie node and 3 edges/relationships merging as 1 into Director node
or
1 single relationship of "ACTED_IN" going towards movie but a number "3" (suggesting there are 3 relationships for that year) written over it

The main goal is to show that there are 3 realtionships related to the year 2016.
I know we can perform aggregations to return tables with count or arrays of data.
But can we do it in graph nodes as well.

NOTE:-I am using Neo4j Browser version 3.1.4

Thank you for reading I hope it's not a silly question.


(Mike R Black) #2

Check out the APOC Merge Nodes


(Groverjatin17) #3

HI Mike.
Thanks for the reply.
I followed exact same steps mentioned.

I created 2 nodes:
Here "Foo" have 202 as id and "Bar" have 203 as id.

CREATE (f:Sample {name:'Foo'}), (b:Sample {surname:'Bar'}) RETURN f,b

Then i run the following CYPHER command:-

MATCH (f:Sample {name:'Foo'}), (b:Sample {surname:'Bar'})
CALL apoc.refactor.mergeNodes([f,b])
YIELD node RETURN node

I get the following error but i do not understand why am i getting it and what to make of it.

Neo.ClientError.Statement.EntityNotFound: Node with id 203 has been deleted in this transaction


(12kunal34) #4

Hey,
please try once below query

MATCH (f:Sample {name:'Foo'}),(b:Sample {surname:'Bar'})
WITH * LIMIT 1
call apoc.refactor.mergeNodes([f,b]) yield node
return "none"

(Groverjatin17) #5

It did nothing. Just showed this:

none
"none"

Nothing else.


(12kunal34) #6

Now search for the node .
It must present in your database.
If it executed well that means merging is complete


(Groverjatin17) #7

wow. It worked.
Thanks.

Can you plz tell why it did not work in previous case. And what did we do differently or the analogy of your solution.


(Groverjatin17) #8

Hi Again,
It worked fine when we have to merge 2 nodes of same Label but with different Properties.
Like properties Name and Surname under common label **Sample** in above comments.

But in my case where properties are common.

For Example:-
Label ABC have 40 nodes with following properties.

{
sid:1 to 40 //Unique for all 40 nodes
counterparty: "Harley Davidson" //same for all 40 nodes.
clientName:"Indian Motors" //Also same for all 40 nodes
}

I used this:-

MATCH (f:ABC{counterparty:'Harley Davidson'}),(b:ABC{counterparty:'Harley Davidson'})
WITH * LIMIT 1
call apoc.refactor.mergeNodes([f,b]) yield node
return "none"

I tried to merge 40 nodes with 1 property as common among all. It executed fine displaying none as output just like previously. But still I see there are 40 nodes under ABC instead of 1.


(Michael Hunger) #10

Which version do you use?


(Groverjatin17) #11

I am using
Neo4j Browser version 3.2.10
Neo4j Server Version 3.4.9(community)
APOC :- apoc-3.4.0.3-all.jar


(Michael Hunger) #12

It doesn't work like that (pairwise merges) as it would do random pairs and then randomly try to merge them where half of them are already gone.

MATCH (f:ABC)
WITH f.counterparty as counterparty, f.clientName as clientName, collect(f) as nodes
WHERE size(nodes) > 1
call apoc.refactor.mergeNodes(nodes) yield node 
return count(*)

(Groverjatin17) #13

Great Sir. It worked.
Tons of thanks.
I need to deep dive rather than just learning match, create and where clauses of Neo4j.
Only if my manager give me time to learn..lol

Again,
Thanks everybody for their input :slight_smile: