I first create this 2:
CREATE (user1:Person {name:"User1"})
CREATE (user2:Person {name:"User2"})
And when I try
CREATE (user1)-[:FOLLOWS]->(user2)
It creates 2 empty nodes with no name nor anything related by the FOLLOW, but both nodes "User1"and "User2" are never blessed by my simple intention of relating them.
Why is this simple thing not working?
You are processing the statements separately. The user1 and user2 are identifiers that apply to a specific cypher statement. By the time you execute the last statement cypher no longer has a reference for user1 and user2.
You could write
match (u1:Person {name:"User1"}), (u2:Person {name:"User2"})
create (u1)-[:FOLLOWS]->(u2)
and that would find the nodes that you had previously created and join them with the :FOLLOWS relationship.
So when you just specified the identifiers int eh create statement it would match every node and join them.
Related
I have a graph containing some nodes with :SubSystem labels. I want to add a new node with a :Document label and create relationships with each of the existing :SubSystem nodes.
When I execute this statement:
MATCH (s:SubSystem)
CREATE (d:Document {title:'New Document'})
CREATE (d)-[:DEPICTS]->(s);
I was surprised when Neo4j created a new :Document node for each :SubSystem. I have 12 sub-systems, so I ended up with 12 new documents each related to one sub-system. I would have expected this behavior had I written:
MATCH (s:SubSystem)
CREATE (:Document {title:'New Document'})-[:DEPICTS]->(s);
But I was expecting that separating the CREATE clauses would create 1 document then create relationships between that document and each of the sub-systems.
Can someone explain why this doesn't work as I was expecting.
EDIT:
I found a solution. This statement does what I wanted, but I still think my original attempt should have worked.
CREATE (d:Document {title:'New Document'})
WITH d MATCH (s:SubSystem) CREATE (d)-[:DEPICTS]->(s);
A MATCH clause generates one or more result rows (or aborts the query if no results are found). A subsequent read/write clause would be executed once per row. Rearranging the order of the clauses, as you did, is one way to work around that (when possible).
I am trying to run the code on this GraphGist to play with the Buendia Family Tree in Neo4j.
When I create two nodes and try to connect them with a relationship, as such:
CREATE (JoseArcadioBuendia:Male {name:'Jose Arcadio Buendia',Gender:'Male'})
then
CREATE (UrsulaIguaran:Female {name:'Ursula Iguaran',Gender:'Female'})
then
CREATE (JoseArcadioBuendia)-[:HUSBAND]->(UrsulaIguaran)
I get this:
Why is this code incorrect? The syntax looks fine and it appears to run for the author of the Gist. Am I doing something incorrectly?
I presume that you did not include all 3 CREATE clauses in a single query.
Cypher identifiers (like JoseArcadioBuendia and UrsulaIguaran) only exist for the life of a single query. The DB does not persist these identifiers. So, if you have a query that contains just CREATE (JoseArcadioBuendia)-[:HUSBAND]->(UrsulaIguaran)), neo4j would not know that the nodes already exist and would therefore create 2 new nodes for you (as well as the relationship).
If you had put all 3 clauses in a single query, you would have seen the results you expected. Otherwise, your query would first have to use MATCH to associate those identifiers with the proper nodes (similar to #Bond's answer).
The third line is incorrect. You are not specifying any nodes. Try the following:
MATCH (a:Male), (b:Female)
WHERE a.name = 'Jose Arcadio Buendia' AND b.name = 'Ursula Iguaran'
CREATE (a)-[:HUSBAND]->(b);
I want to add a relationship between two nodes, but only if the relationship does not exist. For example:
The Relationship between node1 and node2 currently exists with these properties: time:41221323,link:www.google.com
I am trying to add a relationship with different properties for example:
time:5344241,link:www.google.com
In this case i want to keep the original properties on the relationship.
You can use the below CQL query:
MATCH(a: startNodeLabel {attributes to match start node})
MATCH(m:endNodeLabel {attributes to match end node})
MERGE(a)-[:relationshipName]->(m)
The above merge statement creates relation between nodes a and m if there is no existing relationship between a and m.
You want either the MERGE or CREATE UNIQUE clause:
http://neo4j.com/docs/stable/query-merge.html
http://neo4j.com/docs/stable/query-create-unique.html
Also note that MERGE comes with additional ON CREATE SET and ON MATCH SET so you can control when properties get set.
I believe if you give either specific properties as part of the match syntax it will not create only if all of the properties match exactly.
Create Unique clause does serve this purpose. Neo4j Documet says
CREATE UNIQUE is in the middle of MATCH and CREATE — it will match
what it can, and create what is missing. CREATE UNIQUE will always
make the least change possible to the graph — if it can use parts of
the existing graph, it will.
START a=node(...), b=node(...)
CREATE UNIQUE (a)-[r:LIKES]-(b)
return a,b;
I am not sure what I am doing wrong here, so here is how I create nodes
CREATE (urlnode_1:UrlNode {url:'url1', nodenumber:1})
CREATE (urlnode_2:UrlNode {url:'url2', nodenumber:2})
I create relations as follows
CREATE
(urlnode_1)-[:OutLink {anchor_text:['MY']}]->(urlnode_2)
Two nodes are created successfully first, now on running the code to create the relation, I would have liked the relation to exist between the two created nodes but it creates two new nodes say 3 and 4 and shows a relation between them. What am i doing wrong here?
To guide you the best way I can, let's sum up some Neo4j basics concerning node and relationships creation :
A node can have one or more labels, labels are meaned to group the nodes by domain (User, Speaker, Company, etc..see a label as a table name for e.g. ). A node can also have properties.
A relationship can have only ONE type, relationships are organizing the graph. Relationships can also have properties.
To create a node, you can use the CREATE writing clause :
CREATE (n:Person {firstname: 'John'})
The CREATE statement will not check if other nodes with same label and properties already exists, it will just create a new node
Relationships can also be created with the same clause :
MATCH (n:Person {firstname: 'John'}), (p:Person {firstname: 'Pierre'})
CREATE (n)-[:KNOWS]->(p)
A complete pattern can also be created in one go :
CREATE (n:Person {name:'Chris'})-[:KNOWS]->(p:Person {name:'Oliver'})
REMINDER : CREATE will not check for existing nodes.
--- AND NOW MERGE ---
MERGE will lazily check for existing nodes, see him as a MATCH OR CREATE clause :
MERGE (n:Person {firstname:'Fred'})
If the node with label Person and firstname Fred does not exist, the node will be created, otherwise nothing will happen. This is where come the handy ON MATCH and ON CREATE mentionned by #joslinm .
If you run this query multiple times after the node creation, your graph will not change, if you know the http protocol, you can say that MERGE is an indempotent request.
Be aware that, MERGE will ensure that an entire pattern exist in the database, by creating it if it does not already exist, meaning that if you do MERGE with a complete pattern, the entire pattern will be looked up for existence, not a single node :
Say a node with label Person and name property with value 'John' already exist in the db :
MERGE (n:Person {name:'John'})
will not affect the graph
However :
MERGE (n:Person {name:'John'})-[:KNOWS]->(:Person {name:'Nathalia'})
A new John node will be created, because the entire pattern does not exist.
It is recommended to use MERGE incrementally :
MERGE (n:Person {name:'John'})
MERGE (p:Person {name:'Nathalia'})
MERGE (n)-[:KNOWS]->(p)
If you want to know more about the MERGE clause, I can highly recommend you this wonderful article from Luanne on GraphAware : http://graphaware.com/neo4j/2014/07/31/cypher-merge-explained.html
Chris
If you create a relationship, a new one will get created every single time. They are not inherently unique. It sounds like you'd rather be merging the relationship; i.e., if they relationship is there, match it, if not, create it.
The merge syntax for it is as follows:
MERGE (a:Node)-[:LIKES]->(b:Node)
ON
MATCH SET a.msg = 'I matched!'
ON
CREATE SET a.msg = 'I created!'
RETURN a
You can try it out here: http://console.neo4j.org/
You'll notice that first the msg will be "I created!" then after it matches, it will be "I matched!"
I am seeing a really strange problem that the Cypher query is creating multiple nodes when I run the following query and the number of nodes created depends on the how many elements are defined in the IN clause of the query
MATCH (shipper:Shipper)-[:SHIPS_PRODUCT_TYPE]->(prodType:ProductType)
WHERE shipper.InternalId = 1
AND prodType.InternalId IN [11,3,1]
CREATE (load:Shipment {
InternalId: 5,
NodeType: "Shipment",
Created: "2013-11-24T18:25:12.3179997+05:30",
Modified: "0001-01-01T00:00:00+00:00"})
RETURN distinct load AS load, shipper AS shipper
I expect that this query only returns one row of data, but is returning 3 rows as its creating 3 "load:Shipment" nodes with the same data
Am i missing something on how this IN clause has to be used, as I don't even use the match in my create statements for this example?
EDIT
BTW I forgot to mention that I also tried to introduce the With statement as below even then I ended up with multiple nodes
MATCH (shipper:Shipper)-[:SHIPS_PRODUCT_TYPE]->(prodType:ProductType)
WHERE shipper.InternalId = 1
AND prodType.InternalId IN [11,3,1]
WITH shipper, prodType
CREATE (shipper)-[:HAS_PUBLISHED]->(load:Shipment {
InternalId: 5,
NodeType: "Shipment",
Created: "2013-11-24T18:25:12.3179997+05:30",
Modified: "0001-01-01T00:00:00+00:00"})-[:CONTAINS_PRODUCT]->(prodType)
RETURN distinct load AS load, shipper AS shipper
Regards
Kiran
This doesn't really have to do with IN. You are matching more than one result from your initial MATCH/WHERE, so it's creating a node for each result. From the example, I'm not even sure why you're making the initial query, since it's not used in the second part at all. I imagine you mean to connect your new node via a relationship? Maybe you should check out the MERGE command in RC1, which lets you "MATCH or CREATE" a node or a relationship.
Update:
You probably want to use CREATE UNIQUE or MERGE instead of just CREATE, to avoid duplicate nodes. Maybe something like this:
MATCH (shipper:Shipper)-[:SHIPS_PRODUCT_TYPE]->(prodType:ProductType)
WHERE shipper.InternalId = 1
AND prodType.InternalId IN [11,3,1]
WITH shipper, prodType
CREATE UNIQUE (shipper)-[:HAS_PUBLISHED]->(load:Shipment {
InternalId: 5,
NodeType: "Shipment",
Created: "2013-11-24T18:25:12.3179997+05:30",
Modified: "0001-01-01T00:00:00+00:00"})
WITH shipper, load, prodType
CREATE UNIQUE (load)-[:CONTAINS_PRODUCT]->(prodType)
RETURN distinct load AS load, shipper AS shipper