Neo4j - Match then merge statement with a relationship not creating new nodes - neo4j

When I try to add new nodes with labels (Phone, Name) that don't exist yet with a relationship to an existing node the nodes and relationships are not being created.
This is the before and after state with one existing relationship:
MATCH (n:Identity)-[a:ATTR]->(attr) RETURN *
And this is the mutation query:
MATCH (n:Identity {id:'4a028061-8dde-4f64-80c9-ae048e3f81fc'})
MERGE (n)-[na:ATTR]->(name:Name {val: 'John Smith'})
MERGE (n)-[pa:ATTR]->(p:Phone {val:2326410083})
RETURN *
I know this question is similar to Neo4J - Merge statement not creating new nodes with a relationship but, in my case, I am using filters on the nodes. What's am I missing?

Looks like the :Identity node you're trying to match to doesn't exist in the graph.
From your query, you're looking for an identity node with id:'4a028061-8dde-4f64-80c9-ae048e3f81fc', but in the graph image you supplied, if we assume the cut off caption is the id of the identity node, we can tell it starts with:'44b7'
Now it could be that the node you're trying to match on does exist, but doesn't have any outgoing :ATTR relationship (that would explain why it wouldn't be returned by your query), but that's unconfirmed. Does a node with id:'4a028061-8dde-4f64-80c9-ae048e3f81fc' exist in your graph? You haven't shown us that, and if no such node exists then the match would fail, and then there are no rows left for the remaining MERGEs to execute upon.

Related

Is there a way to make a relation when creating a node, on a certain condition? Cypher 3.5

I am new to Neo4j and graph databases.
I am looking for a way create a node while connecting it to another node matching that has a field that matches a certain parameter.
Here's a diagram to get the idea:
Let's say my parameter is :params {friendNodeId: 2}
In my Cypher query, I would like to create my new node with its field name: "my brand new node". Then if there is a node having uniqueId = $params.friendNodeId create a relation between this node and my new node.
My approach is to optimize the entire process by running a single query and not having to make an unnecessary match in a second query to get the newly created node.
If you think that it doesn't make sense at all don't hesitate to come up with another proposition.
Thanks for your help.
From your example in the comments, if the node creation is mandatory, but the relationship creation is optional (depending on if there is a node that matches), then you can just move the CREATE to before your MATCH:
CREATE (new:Node {uId: 4})
SET new.name = "name 4"
WITH new
MATCH (other:Node {uId: $uniqueId})
CREATE (new)-[r:FRIEND]->(other)
RETURN r

Get nodes with or without relationship in neo4j 3.0

Like I have a node by label person
Then there are some alternate nodes attached to it by some relation for the time being I don't know the relation. What I want through report is to know the orphaned nodes in neo4j i.e those that don't have relationship with the Person node or if their relation status property is inactive so its of no use.
I want to create that report in order to remove the orphaned/unused nodes
I have to create a report that should include the following types of nodes.
1. Get All active Alternate Nodes means nodes that have status as Confirmed.
a. Which do not have any incoming relationships.
Or
b. No active incoming relationships means the status property of relationship is not confirmed.
The case is I don't know what relationship is between them I have to just check with or without relationship
I tried cypher query but didn't worked for unknown relationship
I don't see your graph so I created a sample. See below.
If you want to collect all Alona and Inactive nodes, then you can write your query as:
match (n)
where not (n) <--()
and (n.Status = 'Confirmed' or n.Status != 'Confirmed')
return n
which simplifies into:
match (n)
where not (n) <--()
return n
Result:

MERGE Nodes by a Property field

I have different nodes that share one same property field, i need to merge these nodes into one and in the same time copy all the rest of the other properties in the merge node.
example:
(n1,g,p1) (n2,g,p2) (n3,g,p3) =>(n,g,p1,p2,p3)
Important to Note that i don't need the apoc solutions since user defined functions dosen't work in CAPS that i m working at
update :
geohash is the field that have a repeated values, so i want to merge the nodes by this field .
The CAPS team gave me this cypher query to have distinct geohash nodes from the intial graph:
CATALOG CREATE GRAPH temp {
FROM GRAPH session.inputGraph
MATCH (n)
WITH DISTINCT n.geohash AS geohash
CONSTRUCT
CREATE (:HashNode {geohash: geohash})
RETURN GRAPH
}
, however it still missing is the collect of the rest of the properties on the merged nodes.
I haven't a problem for the relationship ,cause we can copy them later from the intial graph:
FROM GRAPH inputGraph
MATCH (from)-[via]->(to)
FROM GRAPH temp
MATCH (n), (m)
WHERE from.geohash = n. AND AND to.geohash = m.geohash
CONSTRUCT
CREATE (n)-[COPY OF via]->(m)
RETURN GRAPH
It's not 100% possible in pure cypher, that's why there is an APOC procedure for that.
To merge two nodes , you have to :
create the merge node with all the properties
to create all the relationship of the nodes on the merge one
For the first part it's possible in cypher. Example :
MATCH (n) WHERE id(n) IN [106, 68]
WITH collect(n) AS nodes
CREATE (new:MyNode)
with nodes, new
UNWIND nodes as node
SET new += properties(node)
RETURN new
But for the second part, you need to be able to create relationship with a dynamic type and dynamic direction, and this is not allowed in cypher ...

fetch path based upon relationship propertty in NEO4j

I want to find all those nodes that are connected to specific node based upon certain relationship label. This is what I have got so far,
Match (n:UMLSConcepts{ConceptID: 'C3254924'})-[:NDFRT {RelationLabel : "RO_may_be_treated_by"}]-> (m:UMLSConcepts) RETURN (n), (m)
where (n) is a specific node and (m) are all other nodes that are connected with this node. Problem with above statement is that it is dependent upon a specific relation type in this case(NDFRT), but I want all relation type that contains certain relationship properties in this case("RO_may_be_treated_by") because there could be path/edge in other relation type as well.
If I I fully understood your question, you can simply omit the relationship type in your Cypher query, this way:
Match (n:UMLSConcepts{ConceptID: 'C3254924'})-[{RelationLabel : "RO_may_be_treated_by"}]-> (m:UMLSConcepts)
RETURN (n), (m)

Making a relation in neo4j

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!"

Resources