Using Neo4j, i have done an implementation of a newsfeeds for each users.
I am using a double linked list with two kind of relation "next_activity" / "prev_activity".
On each activity node i can have others relations as "LIKE".
When a delete an user in my system i would like to delete all the news feeds.
So i have to iterate each activity, delete it (and all relations as LIKE) and be able to go to the next using the relation "next_activity".
Does it possible using Cypher in one request (i mean using the *..100 option).
Thank you!
I have tried (version 1.8.2) :
start user=node:id(id="...") match path=user-[r:NEXT|PREV|LIKES*]->activity
with relationships(path) as act_r, nodes(path) as act_n
foreach(r in act_r : delete r)
with act_n
foreach(n in act_n : delete n);
But i have 'TransactionFailureException"
I am going to test on 1.9.2 RC2
I think something like this should work:
start user=node... // lookup user in index
match p=user-[:NEXT*]-activity // find all activities nodes in the linked list
with nodes(p) as activities // this also includes the user
foreach activity in activities:
match activity-[r?]-() // get all relationships coming off of each activity
delete activities, r; // delete all for each activity
Update: New idea. I'll leave the other idea there for posterity. This should work because it should match each path until the end, and we'll just use the endpoint to delete the :LIKE relationships (or any relationship) going off of those.
start user=node... // lookup user in index
match p=user-[:NEXT*]-activity, activity-[r?]-()
delete user, activity, r;
I built a graph and tested it, so I think it should be a general solution.
http://console.neo4j.org/?id=nnj5h8
Related
When fetching or when I try to delete a specifc node like
MATCH (p)
where ID(p)=79259223
OPTIONAL MATCH (p)-[r]-()
//drops p's relations
DELETE r,p
I get the following error
While loading relationships for Node[79259223] a Relationship[87331456] was encountered that had startNode: 80312215 and endNode: 83719851, i.e. which had neither start nor end node as the node we're loading relationships for
I also run the ConsistencyChecker what resulted in a big list of inconsistencys. However how can you fix these inconsistencys? I can not delete the nodes for instance
Here is a possible way to "fix" an occurrence of this error. Unfortunately, it is a fairly manual approach that has to be used for every node that encounters the same problem.
Before you delete the node, you can try to delete the inconsistent relationship by its native neo4j ID. For example:
MATCH ()-[r]->()
WHERE ID(r) = 87331456
DELETE r;
NOTE: Before deleting that relationship, you should first try to take a look at it (e.g., replace DELETE WITH RETURN) to understand what you are planning to delete. You may want to do something else first or instead.
If that deletion works, then try to delete the node again, as follows:
MATCH (p)
WHERE ID(p) = 79259223
DETACH DELETE p;
Notice that I use the DETACH DELETE syntax, which will attempt to delete all the relationships for the specified node.
I think this may be a bug, however, when deleting a collection of relationships the start node is also deleted. I am running neo4j community edition 2.3.3 and have run the following queries in order.
match (u:User)-[]->(p:Pie)-[c:CONSISTS_OF*1]->() where id(u) = 6398 and id(p)= 6436 return p,c Which returns Displaying 3 nodes, 2 relationships. and the graph in the image
match (u:User)-[]->(p:Pie)-[c:CONSISTS_OF*1]->() where id(u) = 6398 and id(p)= 6436 FOREACH( q in c | DELETE q) Which results in Deleted 2 relationships, statement executed in 103 ms.
And then what I am finding is instead of the collection of relationships c being deleted, the node p is also deleted…
match (u:User)-[]->(p:Pie)-[c:CONSISTS_OF*1]->() where id(u) = 6398 and id(p)= 6436 return p Which results in (no rows)
I would simply like to delete the collection of relationships. I also feel like this feature is something that makes sense but hasn’t been revisited since late 2013… https://github.com/neo4j/neo4j/issues/1612
EDIT: In an earlier version of the question I had DETACH DELETE instead of DELETE. This was a mistake in the posting of the question. I have since revised it. It should be noted that the reason I think this may be a bug is because both DETACH DELETE and DELETE behave the same in this scenario.
In the MATCH query that you use to check whether the (p:Pie) node exists after deleting the relationships you still include the -[c:CONSISTS_OF*1]-> part of the pattern. That part doesn't match anything, because you deleted those relationships. But then the whole pattern won't match anything either, whether or not the node still exists.
You can use MATCH (p:Pie) WHERE id(p) = 6436 to test that the (p:Pie) node still exists.
I have created a linked list structure for a feed scenario. Here i have my feeds persisted in the linked-list in neo4j. This is working fine. However, there might be a need to delete the whole product, so I am trying to come up with a cypher that can delete the product and the related linked list for feeds in one query.
This query returns me correct data
match p = (i:Item {uuid:"d98c299d-239b-40d1-ac2f-01a80ac36db4"})-[:LATEST]-(latestComment), latestComment-[:NEXT*0..]-(olders) return i, latestComment, olders;
based on these lines, I tried writing a delete query and its certain variations using foreach, but nothing seems to be working.
match p = (i:Item {uuid:"d98c299d-239b-40d1-ac2f-01a80ac36db4"})-[:LATEST]-(latestComment), latestComment-[:NEXT*0..]-(olders) delete i, latestComment, olders;
error:
Node record Node[13349,used=false,rel=26286,prop=-1,labels=Inline(0x0:[]),light] still has relationships
a variation with foreach
match (i:Item {uuid:"d98c299d-239b-40d1-ac2f-01a80ac36db4"})-[:LATEST]-(latestComment), latestComment-[:NEXT*0..]-(olders) delete i, foreach (old in olders | delete old)
clearly there is something wrong, but I am not getting enough pointers towards the possible error.
In order to delete a node, you must also delete all relationships touching that node. You queries do not do that.
In your case, since you want to delete the entire path, you might be able to simply do this:
MATCH p =(i:Item { uuid:"d98c299d-239b-40d1-ac2f-01a80ac36db4" })-[latest:LATEST]-(latestComment)-[:NEXT*0..]-(olders)
DELETE p;
However, if any node in the path has relationships that are not also in the path, then the above query need to be modified to include those extra relationships.
I am trying to learn neo4j and was going to start with a basic employee / employer example where an employee has a manager unless at the top of the tree.
My structure looks like employee->MANAGEDBY->manager->MANAGEDBY->manager->MANAGEDBY->manager. However each manger can have multiple employees or managers under them.
What I would like to be able to do is to get a list of all managers between an employee and main boss(ceo/president/whatever).
Initially I started off with a query like this
MATCH(baseEmployee {Name: 'Josh'})-[:MANAGEDBY*0..]-(managers)
RETURN managers.Name;
This seems to not only show my manager and his/her manager and so on but it also seems to show everyone that they manage when what I want to show up is a list like
Josh,
Boss,
BossBoss,
BossBossBoss,
CEO
After some searching and some luck I managed to get closer by using the following query
MATCH p=(baseEmployee {Name: 'Josh'})-[:MANAGEDBY*0..]-(managers)
WHERE NOT(managers-[:MANAGEDBY]->())
RETURN p;
I am just learning neo4j so my best guess of what is happening here is that I get the path from myself to the first manager who doesn't have a MANAGEDBY relationship. My issue is that this returns a path and I would prefer to just have a list of managers.
Is it possible to do this without doing the p= query?
You must add the direction of the relationship to your path query!
Otherwise you also explore downwards from Josh.
And if you start your varlength query at zero 0.. then you return Josh too.
The default is 1.. so you can also leave it off.
You can return the nodes of the path with nodes(p).
MATCH p=(baseEmployee {Name: 'Josh'})-[:MANAGEDBY*]->(managers)
WHERE NOT(managers-[:MANAGEDBY]->())
RETURN nodes(p);
If you want to have one row per node you can do one of two:
Either unwind the collection back into rows.
MATCH p=(baseEmployee {Name: 'Josh'})-[:MANAGEDBY*]->(managers)
WHERE NOT(managers-[:MANAGEDBY]->())
UNWIND nodes(p) as n
RETURN n;
Or return the last node of each path up to the root.
MATCH p=(baseEmployee {Name: 'Josh'})-[:MANAGEDBY*]->(managers)
RETURN managers;
I have a simple social network graph db model. Users can follow other users and post posts. I am trying to get a list of all posts that a user has posted along with any that anyone the user follows has posted
START a=node:node_auto_index(UserIdentifier = "USER0")
MATCH (a)-[:POSTED]->(b), (a)-[:FOLLOWS]->(c)-[:POSTED]->(d)
RETURN b, d;
It is returning the cross product of the two, a tuple of all the values in b joined with all the values in d. (b x d) I would like just a straight list of posts. How do I do this? Do I need to do two separate queries?
Anwsered at https://groups.google.com/forum/?fromgroups=#!topic/neo4j/SdM7bKNRDEA :
START a=node:node_auto_index(UserIdentifier = "USER0")
MATCH (a)-[:POSTED]->(b)
WITH a, collect(b) as posts
MATCH (a)-[:FOLLOWS]->(c)-[:POSTED]->(d)
RETURN posts, collect(d) as followersPosts;
Another way you can do it now (and IMHO the cleaner way) is to take advantage of variable length relationships.
START user=node...
MATCH (user) -[:FOLLOWS*0..1]-> (following) -[:POSTED]-> (post)
RETURN post
The advantage to this way is it lets you aggregate both your own queries and your friends/followings' queries uniformly. E.g. sorting, limiting, paginating, etc.