Could anyone please tell me the difference between Merge and Create in Cypher Querying.
How Neo4j stores data physically?
Thanks in advance..
CREATE does just what it says. It creates, and if that means creating duplicates, well then it creates. MERGE does the same thing as create, but also checks to see if a node already exists with the properties you specify. If it does, then it doesn't create. This helps avoid duplicates. Here's an example: I use CREATE twice to create a person with the same name.
neo4j-sh (?)$ create (p:Person {name: "Bob"});
+-------------------+
| No data returned. |
+-------------------+
Nodes created: 1
Properties set: 1
Labels added: 1
9 ms
neo4j-sh (?)$ create (p:Person {name: "Bob"});
+-------------------+
| No data returned. |
+-------------------+
Nodes created: 1
Properties set: 1
Labels added: 1
5 ms
So now when we query, there are two Bob's.
neo4j-sh (?)$ match (p:Person {name:"Bob"}) return p;
+--------------------------+
| p |
+--------------------------+
| Node[222124]{name:"Bob"} |
| Node[222125]{name:"Bob"} |
+--------------------------+
2 rows
46 ms
Let's MERGE in another Bob and see what happens.
neo4j-sh (?)$ merge (p:Person {name:"Bob"});
+--------------------------------------------+
| No data returned, and nothing was changed. |
+--------------------------------------------+
2 ms
neo4j-sh (?)$ match (p:Person {name:"Bob"}) return p;
+--------------------------+
| p |
+--------------------------+
| Node[222124]{name:"Bob"} |
| Node[222125]{name:"Bob"} |
+--------------------------+
2 rows
11 ms
Bob already existed, so MERGE did nothing here. Querying again, the same two Bobs are present. Had there been no Bobs in the database, MERGE would have done the same thing as CREATE.
Related
using a query I have a list of nodes.
match (n) where n.afield is null return count(n),labels(n) ;
which gives
+---------------------------+
| count(n) | labels(n) |
+---------------------------+
| 7 | ["foo"] |
| 21 | [] |
(...)
If I want to delete all foo labeled node, I would use
match(n:foo) detach delete(n) ;
now, how can I delete all labelless node ? (those 21 in sample above)
match (n) where magic(n) detach delete ;
anyone know some kind of magic(n) ?
You can try this query to delete node without labels:
MATCH (n) where size(labels(n)) = 0
DETACH DELETE n
i have a csv file containing activities (process graph) :
startActivityId,Name,endActivityId
1,A,2
2,B,3
3,C,4
4,D,5
so that it will look like this : A->B->C->D
i imported the csv file successfully into neo4j server : using this Cypher query :
USING PERIODIC COMMIT
LOAD CSV WITH HEADERS FROM "file:path/graph/activity.csv" AS row
CREATE (:Activity {startactivityId:row.startActivityId, Name: row.Name, endActivityId: row.endActivityId});
i then created an index on startactivityId :
CREATE INDEX ON :activity(startActivityId);
then i want to create the relationships between these nodes, so tried this cypher query :
USING PERIODIC COMMIT
LOAD CSV WITH HEADERS FROM "file:path/graph/activity.csv" AS row
MATCH (startActivity:Activity {startActivityId: row.startActivityId})
MATCH (endActivity:Activity {startActivityId: row.endActivityId})
MERGE (startActivity)-[:LINKS_TO]->(endActivity);`
but no relationships created, nothing happens
i'm sure i missed something cause i'm new to cypher but i can't figure it out.
any ideas ?
I copied your updated csv (and removed the whitespace at the head of the first column) and ran your queries.
neo4j-sh (?)$ USING PERIODIC COMMIT LOAD CSV WITH HEADERS FROM "file:///Users/jonatan/src/doc/stackexchange/32225817.pdc" as row CREATE (:Activity {startActivityId:row.startActivityId, name:row.Name, endActivityId:row.endActivityId});
+-------------------+
| No data returned. |
+-------------------+
Nodes created: 4
Properties set: 12
Labels added: 4
115 ms
neo4j-sh (?)$ USING PERIODIC COMMIT LOAD CSV WITH HEADERS FROM "file:///Users/jonatan/src/doc/stackexchange/32225817.pdc" as row MATCH (s:Activity {startActivityId:row.startActivityId}) MATCH (e:Activity {startActivityId:row.endActivityId}) MERGE (s)-[r:LINKS_TO]->(e) RETURN r;
+-------------------+
| r |
+-------------------+
| :LINKS_TO[2084]{} |
| :LINKS_TO[2085]{} |
| :LINKS_TO[2086]{} |
+-------------------+
3 rows
Relationships created: 3
178 ms
Three relationships created. To confirm that they are the right relationships I match and return the path (:Activity)-[:LINKS_TO]->().
neo4j-sh (?)$ MATCH p=(:Activity)-[:LINKS_TO]->() RETURN p;
+-------------------------------------------------------------------------------------------------------------------------------------------+
| p |
+-------------------------------------------------------------------------------------------------------------------------------------------+
| [Node[1415]{name:"A",startActivityId:"1",endActivityId:"2"},:LINKS_TO[2084]{},Node[1416]{name:"B",startActivityId:"2",endActivityId:"3"}] |
| [Node[1416]{name:"B",startActivityId:"2",endActivityId:"3"},:LINKS_TO[2085]{},Node[1417]{name:"C",startActivityId:"3",endActivityId:"4"}] |
| [Node[1417]{name:"C",startActivityId:"3",endActivityId:"4"},:LINKS_TO[2086]{},Node[1418]{name:"D",startActivityId:"4",endActivityId:"5"}] |
+-------------------------------------------------------------------------------------------------------------------------------------------+
3 rows
49 ms
neo4j-sh (?)$
It looks OK to me, not sure what's not working for you.
What does MATCH p=(:Activity)-[r]->() RETURN p; tell you?
I have some nodes like these:
neo4j-sh (?)$ match (n:Woka) return count (n);
+-----------+
| count (n) |
+-----------+
| 19798966 |
+-----------+
1 row
How I can change them from "Woka" to "Book" without delete and recreate?
you can use set and remove
MATCH (n:Woka)
SET n:Book
REMOVE n:Woka
I have big number of EmpBase imprted (from csv file from postgreSQL )nodes like:
neo4j-sh (?)$ match (e:EmpBase) return e limit 10;
+-------------------------------------------------------------------------+
| e |
+-------------------------------------------------------------------------+
| Node[8992]{neo_eb_id:8993,neo_eb_name:"emp_no_8993",neo_eb_bossID:5503} |
| Node[8993]{neo_eb_id:8994,neo_eb_name:"emp_no_8994",neo_eb_bossID:8131} |
| Node[8994]{neo_eb_id:8995,neo_eb_name:"emp_no_8995",neo_eb_bossID:8624} |
What cypher query can create self relations on every node so that every node with neo_eb_bossid can have the relationship to the adequate node ?
In postgreSQl the data is about 1020MB table. In Neo4j, after import, it is 6.42 GiB as the console says.
In order to create the relationship based on neo_eb_bossID, you can match the nodes and run a foreach loop that will create the relationships to the related node :
MATCH (e:EmpBase) WITH collect(e) AS empbases
FOREACH (emp in empbases |
MERGE (target:EmpBase {neo_eb_id:emp.neo_eb_bossID}
MERGE (emp)-[:YOUR_RELATIONSHIP]->(target)
)
Concerning the self relationship, I've hard to understand what you exactly want.
Chris
I was following the Neo4J online tutorial and I came to a question while trying this query with the query tool:
match (a:Person)-[:ACTED_IN|:DIRECTED]->()<-[:ACTED_IN|:DIRECTED]-(b:Person)
return a,b;
I was expecting one of the pairs returned to have the same Person in both identifiers but that didn't happen. Can somebody explain me why? Does a match clause exclude repeated elements in the different identifiers used?
UPDATE:
This question came to me in "Lession 3 - Adding Relationships with Cypher, more" from Neo4J online tutorial, where the query I mentioned above is presented.
I refined the query to the following one, in order to focus more directly my question:
MATCH (a:Person {name:"Keanu Reeves"})-[:ACTED_IN]->()<-[:ACTED_IN]-(b)
RETURN a,b;
The results:
|---------------|--------------------|
| a | b |
|---------------|--------------------|
| Keanu Reeves | Carrie-Anne Moss |
| Keanu Reeves | Laurence Fishburne |
| Keanu Reeves | Hugo Weaving |
| Keanu Reeves | Brooke Langton |
| Keanu Reeves | Gene Hackman |
| Keanu Reeves | Orlando Jones |
|------------------------------------|
So, why there is no row with Keanu Reeves in a and b? Doesn't he should match with both both relations :ACTED_IN?
The behavior you observed is by design.
To quote the manual:
While pattern matching, Cypher makes sure to not include matches where
the same graph relationship is found multiple times in a single
pattern. In most use cases, this is a sensible thing to do.
I would check your data sample. Your query looks like it works just fine for me. I replicated with a simple data set, and here's verification that it does produce pairs like what you're looking for.
Joe acted in "Some Flick"
neo4j-sh (?)$ create (p:Person {name:"Joe"})-[:ACTED_IN]->(m:Movie {name:"Some Flick"});
+-------------------+
| No data returned. |
+-------------------+
Nodes created: 2
Relationships created: 1
Properties set: 2
Labels added: 2
14 ms
But Joe is so multi-talented, he also directed "Some Flick".
neo4j-sh (?)$ match (p:Person {name: "Joe"}), (m:Movie {name: "Some Flick"}) create p-[:DIRECTED]->m;
+-------------------+
| No data returned. |
+-------------------+
Relationships created: 2
23 ms
So who are the actor/director pairs that we know of?
neo4j-sh (?)$ match (a:Person)-[:ACTED_IN|:DIRECTED]->()<-[:ACTED_IN|:DIRECTED]-(b:Person)
> return a,b;
+-----------------------------------------------------+
| a | b |
+-----------------------------------------------------+
| Node[222128]{name:"Joe"} | Node[222128]{name:"Joe"} |
| Node[222128]{name:"Joe"} | Node[222128]{name:"Joe"} |
+-----------------------------------------------------+
2 rows
50 ms
Of course it's Joe.