How to delete and merge outgoing relationships on the same query - neo4j

I am using cypher. I am trying to delete all out going relationships before creating new ones on the same query.
i have weird situation if the relations/nodes already existed it's working as expected. if They never been created before I get:
(no changes, no rows)
This is my query:
match (user{userId:'a'})-[r:nearby_wifi]->() delete r
MERGE (p1:BT{userId:'a'}) WITH p1, [{bssid:"0a:18:d6:c1:3d:fd",level:"-51",timestamp:"1973-08-27 02:26:35.423",venueName:""},{bssid:"04:18:d6:c2:3e:2a",level:"-55",timestamp:"1973-08-27 02:26:35.425",venueName:""},{bssid:"0e:18:d6:c1:3d:fd",level:"-53",timestamp:"1973-08-25 11:06:07.392",venueName:""}] AS wifis
UNWIND wifis AS wifi
MERGE (p2:WIFI{bssid: wifi.bssid})
MERGE (p1)-[r1:nearby_wifi]->(p2)
SET r1.dist=wifi.dist
SET p1.lastTimeActive=1460378030215
SET p2.level=wifi.level
SET p2.timestamp=wifi.timestamp
SET p2.venueName=wifi.venueName
Any idea why when combining delete and the merge executions I got no changes(when graph empty)?
Thanks.

Replace first match with optional match
For example if you have no client nodes in your database, but have some person nodes query
Match (p:Client) with p Match (r:Person) return *
will get nothing, but query
Optional Match (p:Client) with p Match (r:Person) return *
will give you Persons. I think neo4j optimizer stops executing query after it gets no results and with optional match it gets null, and continues executing.

Related

write a query that return that return supplementary relationship between two nodes in neo4j

I have a neo4j db which have this form
(:FBuser)-[:Published]->(:Post)<-[:Tagged_in]-(:Friend)<-[:Tagged_together]->(:Friend)
A Post (:Node) could have two or more Nodes (:Friend) connected with it.
I want to write a query that returns this schema
(:FBuser)-[:Friend]->(n:Friend)-[:Tagged_in]->(:Post)<-[:Tagged_in]-(m:Friend)<-[:Tagged_together]->(n)
where for (:Post) I need all the post for that specific (n:Friend). The problem is that not all the (:Post) has connected with another (m:Friend) so, only for some nodes I have (n:Friend)<-[:Tagged_together]->(m:Friend)
I write this code but obviously returns just all the nodes (:Post) for a specific node (:Friend) and supplementary (:Friend) connected with it
MATCH t=(:fbUser)-[:FRIEND]-(w)-[:TAGGED_IN]-(p)
MATCH s=(:Friend)-[:TAGGED_IN]-(q)
WHERE
w.name=~ '(?i).*edoardo.*' AND
q.timestamp=p.timestamp AND
w.nodeDegree>=0
RETURN t,s
How can I solve the problem ?
Try optional match. https://neo4j.com/docs/cypher-manual/current/clauses/optional-match/
I used a coalesce statement so that the timestamp filter will still return records if q is null.
MATCH t=(:fbUser)-[:FRIEND]-(w)-[:TAGGED_IN]-(p)
OPTIONAL MATCH s=(:Friend)-[:TAGGED_IN]-(q)
WHERE
w.name=~ '(?i).*edoardo.*' AND
coalesce(q.timestamp, p.timestamp)=p.timestamp AND
w.nodeDegree>=0
RETURN t,s

Delete relationships and then add back to node neo4j

I would like to get a node, delete all outgoing relationships of a certain type and then add back relationships.
The problem I have is that once I grab the node, it still maintains it's previous relationships even after delete so instead of having 1 it keeps doubling whatever it has. 1->2->4->8 etc
Sample graph:
CREATE (a:Basic {name:'a'})
CREATE (b:Basic {name:'b'})
CREATE (c:Basic {name:'c'})
CREATE (a)-[:TO]->(b)
CREATE (a)-[:SO]->(c)
The query to delete the previous relationships and then add in the new relationships. (this is just a brief sample where in reality it wouldn't add back the same relationships, but more then likely point it to a different node).
MATCH (a:Basic {name:'a'})
WITH a
OPTIONAL MATCH (a)-[r:TO|SO]->()
DELETE r
WITH a
MATCH (b:Basic {name:'b'})
CREATE (a)-[:TO]->(b)
WITH a
MATCH (c:Basic {name:'c'})
CREATE (a)-[:SO]->(c)
If I change the CREATE to MERGE then it solves the problem, but it feels odd to have to merge when I know that I just deleted all the relationships. Is there a way to update "a" midway through the query so it reflects the changes? I would like to keep it in one query
The behavior you observed is due the subtle fact that the OPTIONAL MATCH clause generated 2 rows of data, which caused all subsequent operations to be done twice.
To force there to be only a single row of data after the DELETE clause, you can use WITH DISTINCT a (instead of WITH a) right after the DELETE clause, like this:
MATCH (a:Basic {name:'a'})
OPTIONAL MATCH (a)-[r:TO|SO]->()
DELETE r
WITH DISTINCT a
MATCH (b:Basic {name:'b'})
CREATE (a)-[:TO]->(b)
WITH a
MATCH (c:Basic {name:'c'})
CREATE (a)-[:SO]->(c)

Duplicate object in a list when I try to map all related entities

According to this post I tried to map all related entities in a list.
I used the same query into the post with a condition to return a list of User but it returns duplicate object
MATCH (user:User) WHERE <complex conditions>
WITH user, calculatedValue
MATCH p=(user)-[r*0..1]-() RETURN user, calculatedValue, nodes(p), rels(p)
Is it a bug? I'm using SDN 4.2.4.RELEASE with neo4j 3.2.1
Not a bug.
Keep in mind a MATCH in Neo4j will find all occurrences of a given pattern. Let's look at your last MATCH:
MATCH p=(user)-[r*0..1]-()
Because you have a variable match of *0..1, this will always return at least one row with just the user itself (with rels(p) empty and nodes(p) containing only the user), and then you'll get a row for every connected node (user will always be present on that row, and in the nodes(p) collection, along with the other connected node).
In the end, when you have a single user node and n directly connected nodes, you will get n + 1 rows. You can run the query in the Neo4j browser, looking at the table results, to confirm.
A better match might be something like:
...
OPTIONAL MATCH (user)-[r]-(b)
RETURN user, calculatedValue, collect(r) as rels, collect(b) as connectedNodes
Because we aggregate on all relationships and connected nodes (rather than just the relationships and nodes for each path), you'll get a single row result per user node.

Unable to load NODE with id

I recently upgraded my Neo4j database to v. 3 (3.0.6). Since then I am having trouble when trying to delete nodes with Cypher. This is a new problem since the upgrade. They Cypher query is:
MATCH (p) WHERE id(p) = 83624
OPTIONAL MATCH (p)-[r]-(n)
OPTIONAL MATCH (p)-[r2]-(n2)
WHERE NOT ('Entity' in labels(n2))
DELETE r, r2, p, n2
This now results in the error Unable to load NODE with id 83624
The exact query with RETURN instead of DELETE returns the node. I've also tried swapping out DELETE with DETACH DELETE of the nodes, but that gives me the same error.
It looks like this question has been asked before but without a solution. Any idea what is causing this error?
I'm a little confused by this query. Both of your optional matches are identical, in that they will match to any relationship to any node connected to p.
Let me make sure I understand what you're trying to do: Find a node by ID, then delete that node along with any connected node that is not an Entity (as well as the relationships connecting them). Is that right?
If so, this query might work better:
MATCH (p) WHERE id(p) = 83624
OPTIONAL MATCH (p)--(n)
WHERE NOT n:Entity
DETACH DELETE n
DETACH DELETE p
Detaching a node deletes all relationships connected to that node, and you can only delete a node that has zero relationships.
Also, just to note, it's not a good idea to use the internal ids for uniquely identifying nodes. It's recommended to use your own unique IDs instead, and create unique constraints on that property for that label.

Keep track of Changes in Neo4j - Achieve functionality like a "flag" variable in standard programming

Initial setup of the sample database is provided link to console
There are various cases and within each case, there are performers(with properties id and name). This is the continuation of problems defined problem statement and solution to unique node creation
The solution in the second link is (credits to Christophe Willemsen
)
MATCH (n:Performer)
WITH collect(DISTINCT (n.name)) AS names
UNWIND names as name
MERGE (nn:NewUniqueNode {name:name})
WITH names
MATCH (c:Case)
MATCH (p1)-[r:RELATES_TO]->(p2)<-[:RELATES]-(c)-[:RELATES]->(p1)
WITH r
ORDER BY r.length
MATCH (nn1:NewUniqueNode {name:startNode(r).name})
MATCH (nn2:NewUniqueNode {name:endNode(r).name})
MERGE (nn1)-[rf:FINAL_RESULT]->(nn2)
SET rf.strength = CASE WHEN rf.strength IS NULL THEN r.value ELSE rf.strength + r.value END
This solution achieved what was asked for.
But I need to achieve something like this.
foreach (Case.id in the database)
{
foreach(distinct value of r.Length)
{
//update value property of node normal
normal.value=normal.value+0.5^(r.Length-2)
//create new nodes and add the result as their relationship or merge it to existing one
MATCH (nn1:NewUniqueNode {name:startNode(r).name})
MATCH (nn2:NewUniqueNode {name:endNode(r).name})
MERGE (nn1)-[rf:FINAL_RESULT]->(nn2)
//
rf.strength=rf.strength + r.value*0.5^(r.Length-2);
}
}
The problem is to track the change in the case and then the r.Length property. How can it be achieved in Cypher?
I will not redo the last part, where setting strengths.
One thing though, in your console link, there is only one Normal node, so why do you need to iterate over each case, you can just match distinct relationships lengths.
By the way for the first part :
MATCH (n:Case)
MATCH (n)-[:RELATES]->()-[r:RELATES_TO]->()<-[:RELATES]-(n)
WITH collect(DISTINCT (r.length)) AS lengths
MATCH (normal:Normal)
UNWIND lengths AS l
SET normal.value = normal.value +(0.5^l)
RETURN normal.value
Explanations :
Match the cases
Foreach case, match the RELATES_TO relationships of Performers for that Case
collect distinct lengths
Match the Normal node, iterate the the distinct lengths collection and setting the proper value on the normal node

Resources