Cypher - Delete node with given property and reconnect graph - neo4j

I have a graph consisting of paths.
I need to delete all nodes, that have a property:
linksTo:'javascript'
After deleting i have to reconnect the paths. This means i need to create a new relationship for each gap. This relationship has a property named deltaTime that holds some integer value. This value (deltaTime) should be the sum of all deltaTime-properties of the deleted relationships of this path. Please look at the following picture for better understanding.
I don't know how to detect multiple "bad" nodes in a row, with a variable row-length.

It would help if you could provide the labels involved in your graph, as well as the relationship types you're using.
Assuming all these paths are chains (only single relationships connecting each node), something like this should work for you:
// first, add a label on all the nodes we plan on deleting
// it helps if they already have the same label especially if linksTo property is indexed.
MATCH (n{linksTo:'javascript'})
SET n:ToDelete
With the appropriate nodes labeled, we'll find the segments of nodes to delete, the surrounding nodes that need to be connected, and create the new relationship. We ensure a and b are start and end nodes of the chain by ensuring there are no :ToDelete nodes linking to a, or from b.
MATCH (a:ToDelete)
WHERE NOT (:ToDelete)-->(a)
AND ()-->(a)
MATCH p = (a)-[rel*0..]->(b:ToDelete)
WHERE ALL(node in nodes(p) WHERE node:ToDelete)
AND NOT (b)-->(:ToDelete)
AND (b)-->()
WITH a, b, REDUCE(s = 0, r IN rel | s + r.value) as sum
// now get the adjacent nodes we need to connect
MATCH (x)-[r1]->(a), (b)-[r2]->(y)
WITH x, y, sum + r1.value + r2.value AS sumValue
// making up relationship type and property name as I don't know what you're using
MERGE (x)-[:Rel{value: sumValue}]->(y)
Finally, when you're sure the new relationships look correct, delete the nodes you no longer need.
MATCH (n:ToDelete)
DETACH DELETE n

Related

NEO4J nodes under a node filter by relationship

How can we add a relationship to the query.
Say A-[C01]-B-[C02]-D and A-[C01]-B-[C03]-E
C01 C02 C03 are relationship codes I want to get output
B E
because I want only nodes that can be reached unbroken by C01 or C03
How can I get this result in Cypher?
You may want to clarify, what you're asking for seems like a very simple case of matching. You may want to provide some more info, such as node labels and how you're matching to your start nodes, since without these we have to make things up for example code.
MATCH (a:Thing)
WHERE a.ID = 123
WITH a
MATCH (a)-[:C01|C03*]->(b:Thing)
RETURN b
The key here is specifying multiple relationship types to traverse, using * for multiplicity, so it will match on all nodes that can be reached by any chain of those relationships.

Find all relations starting with a given node

In a graph where the following nodes
A,B,C,D
have a relationship with each nodes successor
(A->B)
and
(B->C)
etc.
How do i make a query that starts with A and gives me all nodes (and relationships) from that and outwards.
I do not know the end node (C).
All i know is to start from A, and traverse the whole connected graph (with conditions on relationship and node type)
I think, you need to use this pattern:
(n)-[*]->(m) - variable length path of any number of relationships from n to m. (see Refcard)
A sample query would be:
MATCH path = (a:A)-[*]->()
RETURN path
Have also a look at the path functions in the refcard to expand your cypher query (I don't know what exact conditions you'll need to apply).
To get all the nodes / relationships starting at a node:
MATCH (a:A {id: "id"})-[r*]-(b)
RETURN a, r, b
This will return all the graphs originating with node A / Label A where id = "id".
One caveat - if this graph is large the query will take a long time to run.

Cypher - traversal of nodes

I have a simple graph with nodes labeled as Organization and two directed relationship types 'Control' and 'Influence'. My objective is -
Step-1
Given a node, find all nodes connected to it with 'Control' relationship (in any direction)
Step-2
For all nodes found by Step-1, find any outbound 'Influence' relationships (of any length) and include those nodes as well
What I have been able to come up thus far:
MATCH (x:Organization {ORGID: "5621"})-[:Control*1..]-(y) WITH y MATCH y-[:Influence*0..]-(z) RETURN y,z;
Questions
1) This query does not include the starting node, how can I get that in the result?
2) Ideally I'd like to get the relationships in the result also, it just returns the nodes
TIA
Here is one way to do what you want:
MATCH (x:Organization { ORGID: "5621" }), p1 = x-[:Influence*0..]->(z)
WHERE NOT z-[:Influence]->()
WITH x, COLLECT(p1) AS c1
OPTIONAL MATCH x-[:Control*]-(y), p2=y-[:Influence*0..]->(z)
WHERE NOT z-[:Influence]->()
RETURN c1 + COLLECT(p2) AS result;
The query returns a collection of matching Influence paths. The WHERE clauses are used to make sure that each path is as long as possible (to avoid a lot of duplicate subpaths from showing up in the results). Every path is a collection of node(s) separated by relationships, and can consist of just a node if the path has no relationships.

How do I return nodes in neo4j that have a certain relationship, and then return nodes that have a different relationship with the first nodes?

I have a bunch of nodes that "refer" to other nodes. The nodes referred to (refer_to being the relationship) may then have a relationship to another node called changed_to. Those nodes that are related by the changed_to relationship may also have another changed_to relationship with yet another node. I want to return the nodes referred to, but also the nodes that the referred nodes were changed into. I tried a query that returns referred to nodes combined with a union with an optional match of ReferencedNode changed to ResultNode, but I don't think this will work as it will only get me the referenced node plus the first changed to node and nothing after that, assuming that would work at all to begin with. How can I make a query with the described behavior?
Edit:
This is an example of the relationships going on. I would like to return the referenced to node and the node that the referenced node was ultimately became, with some indicator showing that it became that node ultimately.
Can you give some examples of queries you've tried? Here's what I'm thinking:
MATCH path=(n)-[:refer_to]->(o)-[:changed_to*1..5]->(p)
WHERE n.id = {start_id}
RETURN nodes(path), rels(path)
Of course I don't know if you have an id property so that might need to change. Also you'll be passing in a start_id parameter here.
If you want to return the "references" node and the last "changed_to" node if there is one, you can first match the relationship you know is there, then optionally match at variable depth the path that may be there. If there is more than one "changed_to" relationship you will have more than one result item at this point. If you want all the "changed_to" nodes you can return now, but if you want only the last one you can order the result items by path depth descending with a limit of 1 to get the longest path and then return the last node in that path. That query could look something like
MATCH (n)-[:REFERENCES]->(o)
WHERE n.uid = {uid}
OPTIONAL MATCH path=o-[:CHANGED_TO*1..5]->(p)
WITH n, o, path
ORDER BY length(path) DESC
LIMIT 1
RETURN n, o, nodes(path)[-1]
This returns the start node, the "references" node and
nothing when there is no "changed_to" node
the one "changed_to" node when there is only one
the last "changed_to" node when there is more than one
You can test the query in this console. It contains these three cases and you can test them by replacing {uid} above with the values 1,5 and 8 to get the starting nodes for the three paths.

In neo4j is there a way to get path between more than 2 random nodes whose direction of relation is not known

I have a scenario where I have more than 2 random nodes.
I need to get all possible paths connecting all three nodes. I do not know the direction of relation and the relationship type.
Example : I have in the graph database with three nodes person->Purchase->Product.
I need to get the path connecting these three nodes. But I do not know the order in which I need to query, for example if I give the query as person-Product-Purchase, it will return no rows as the order is incorrect.
So in this case how should I frame the query?
In a nutshell I need to find the path between more than two nodes where the match clause may be mentioned in what ever order the user knows.
You could list all of the nodes in multiple bound identifiers in the start, and then your match would find the ones that match, in any order. And you could do this for N items, if needed. For example, here is a query for 3 items:
start a=node:node_auto_index('name:(person product purchase)'),
b=node:node_auto_index('name:(person product purchase)'),
c=node:node_auto_index('name:(person product purchase)')
match p=a-->b-->c
return p;
http://console.neo4j.org/r/tbwu2d
I actually just made a blog post about how start works, which might help:
http://wes.skeweredrook.com/cypher-it-all-starts-with-the-start/
Wouldn't be acceptable to make several queries ? In your case you'd automatically generate 6 queries with all the possible combinations (factorial on the number of variables)
A possible solution would be to first get three sets of nodes (s,m,e). These sets may be the same as in the question (or contain partially or completely different nodes). The sets are important, because starting, middle and end node are not fixed.
Here is the code for the Matrix example with added nodes.
match (s) where s.name in ["Oracle", "Neo", "Cypher"]
match (m) where m.name in ["Oracle", "Neo", "Cypher"] and s <> m
match (e) where e.name in ["Oracle", "Neo", "Cypher"] and s <> e and m <> e
match rel=(s)-[r1*1..]-(m)-[r2*1..]-(e)
return s, r1, m, r2, e, rel;
The additional where clause makes sure the same node is not used twice in one result row.
The relations are matched with one or more edges (*1..) or hops between the nodes s and m or m and e respectively and disregarding the directions.
Note that cypher 3 syntax is used here.

Resources