Neo4J common neighbors of a set nodes in a path - neo4j

My network consists of nodes and the relationship is a numeric number. Think of it as a set of cities, and the relationship is the whether there is a road and if so how far is it.
I have path from my neo4j query, wonder how I can find the neighbor of this path given the following condition. These neighbors should be neighbor to more than one node in the path.
In the following picture, I have tried to illustrate what I mean. My path looks like the blue star below. I would like to find the green nodes. These green nodes, are connected to two or more nodes in the path. I have draw a few of these green nodes.
As an output I would like to have a path that include the blue path as well as the green ones.
EDIT
My original path looks like
If I use the suggested solution by #NonameCurious, I will have
As you can see the result is a group of nodes which there is no relationship. I assume it is because the query only returns nodes. However, I would like to have the connection between those "neighbors" with the original path be displayed on top of the original path.

How about this:
WITH nodes(path) AS nodes
UNWIND nodes AS node
MATCH (a)--(node) WHERE NOT a IN nodes
WITH a, COUNT(DISTINCT node) AS relCounts
WITH a WHERE relCounts > 1
RETURN a
I am assuming path is given.
UPDATE:
If you need to filter relationships, you can use something like this:
WITH nodes(path) AS nodes
UNWIND nodes AS node
MATCH (a)-[r]-(node) WHERE NOT a IN nodes AND r.score > 27
WITH a, COUNT(DISTINCT node) AS relCounts
WITH a WHERE relCounts > 1
RETURN a
SECOND UPDATE:
If you just want to somehow get a subgraph of all the new nodes along with the old ones, you can do this
WITH nodes(path) AS nodes, path UNWIND nodes AS node MATCH (a)-[r]-(node)
WHERE NOT a IN nodes AND r.score > 27
WITH a, COLLECT(DISTINCT node) AS connectedNodes, COLLECT(DISTINCT r) AS connectedRels, path WHERE SIZE(connectedNodes) > 1
UNWIND connectedNodes AS connectedNode
UNWIND connectedRels AS connectedRel
RETURN a, connectedRel, connectedNode, path

Related

Neo4J: How can I find if a path traversing multiple nodes given in a list exist?

I have a graph of nodes with a relationship NEXT with 2 properties sequence (s) and position (p). For example:
N1-[NEXT{s:1, p:2}]-> N2-[NEXT{s:1, p:3}]-> N3-[NEXT{s:1, p:4}]-> N4
A node N might have multiple outgoing Next relationships with different property values.
Given a list of node names, e.g. [N2,N3,N4] representing a sequential path, I want to check if the graph contains the nodes and that the nodes are connected with relationship Next in order.
For example, if the list contains [N2,N3,N4], then check if there is a relationship Next between nodes N2,N3 and between N3,N4.
In addition, I want to make sure that the nodes are part of the same sequence, thus the property s is the same for each relationship Next. To ensure that the order maintained, I need to verify if the property p is incremental. Meaning, the value of p in the relationship between N2 -> N3 is 3 and the value p between N3->N4 is (3+1) = 4 and so on.
I tried using APOC to retrieve the possible paths from an initial node N using python (library: neo4jrestclient) and then process the paths manually to check if a sequence exists using the following query:
q = "MATCH (n:Node) WHERE n.name = 'N' CALL apoc.path.expandConfig(n {relationshipFilter:'NEXT>', maxLevel:4}) YIELD path RETURN path"
results = db.query(q,data_contents=True)
However, running the query took some time that I eventually stopped the query. Any ideas?
This one is a bit tough.
First, pre-match to the nodes in the path. We can use the collected nodes here to be a whitelist for nodes in the path
Assuming the start node is included in the list, a query might go like:
UNWIND $names as name
MATCH (n:Node {name:name})
WITH collect(n) as nodes
WITH nodes, nodes[0] as start, tail(nodes) as tail, size(nodes)-1 as depth
CALL apoc.path.expandConfig(start, {whitelistNodes:nodes, minLevel:depth, maxLevel:depth, relationshipFilter:'NEXT>'}) YIELD path
WHERE all(index in range(0, size(nodes)-1) WHERE nodes[index] = nodes(path)[index])
// we now have only paths with the given nodes in order
WITH path, relationships(path)[0].s as sequence
WHERE all(rel in tail(relationships(path)) WHERE rel.s = sequence)
// now each path only has relationships of common sequence
WITH path, apoc.coll.pairsMin([rel in relationships(path) | rel.p]) as pairs
WHERE all(pair in pairs WHERE pair[0] + 1 = pair[1])
RETURN path

How can I find the set of lowest parents (or ancestors) nodes of P1 that cut all paths between P1 and P2

Suppose that I have the following graph. How can I find the lowest set of nodes that cut all (oriented) paths between nodes [1,2,3,4] and node [66]. In my case I want to find nodes [11, 5,9, 6] (node 7 must be excluded because node 6 and 9 are more lower ancestor to nodes 3 and 4. Thank you for your helps.
I have an answer to a similar question here.
Here are the steps I would take:
Match to the starting nodes [1,2,3,4] and collect them for later.
Match to and expand out from your end node (66) to all connected nodes (using the directed pattern), blacklisting the starting nodes from step 1 (so we don't include paths to those nodes or beyond them). Collect these nodes as descendents.
Expand from your starting nodes, terminating at descendents (so we get paths to the first descendent encountered, but don't continue expanding past any of them).
Cypher doesn't have great support for performing the termination during expansion behavior in step 3, so we need path expander procs from APOC Procedures for that.
Let's say that these are nodes of type :Node with id properties for the numeric values, with :PARENT relationships between them pointing toward parents/ancestors. Let's say we have an index on :Node(id) for quick lookup. Using APOC our query would look something like:
MATCH (n:Node)
WHERE n.id IN [1,2,3,4]
WITH collect(n) as startNodes
MATCH path = (end:Node {id:66})<-[:PARENT*]-(descendent)
WHERE none(node in nodes(path) WHERE node in startNodes)
WITH startNodes, end, collect(DISTINCT descendent) as descendents
CALL apoc.path.subgraphNodes(startNodes, {terminatorNodes:descendents}) YIELD node as mostRecentDescendents
RETURN mostRecentDescendents

Neo4j: Return only root nodes from possible child paths

I have a set of (n) values which all have corresponding nodes in my graph. I start with unknown relationships to each other. (see start nodes in blue)
I want to find, as simply as possible, is if any of the value/nodes are children of any of the others then applying these rules to filter the results:
If the node is a child then discard it. (white nodes)
If the node is a root then return it. (green nodes)
If the node does not have any children also return it. (green node 673)
There can be up to 50 starting nodes. I've tried iterating through them comparing two at a time discarding them if they are a child - but the number of iterations quickly gets out of hand in larger sets. I'm hoping there is some graph magic I've overlooked. Cypher please!
Thanks!
Let's say that you have an input parameter nids - set of values for the id property of node, target nodes have the label Node, the relationship between nodes is of type hasChild.
Then you need to find such nodes corresponding to the input set, and which do not have parents from the nodes corresponding to the input set:
UNWIND {nids} as nid
MATCH (N:Node {id: nid})
OPTIONAL MATCH (N:Node {id: nid})<-[:hasChild]-(P:Node) WHERE P.id IN {nids}
WITH N, collect(P) AS ts WHERE size(ts) = 0
RETURN N
And do not forget to add an index to the id property for the node:
CREATE INDEX ON :Node(id)

Using Cypher how would one select all nodes connected to a node within exactly one hop whilst excluding the central node from the result?

Take the above image as an example. Using Cypher, how would I match all of the nodes except for the longest chain and the central node? I.e. all nodes within exactly one hop of the central node whilst excluding the central node (all nodes and edges except 3 nodes and 2 edges).
I have tried the following:
MATCH (n:Node) WHERE n.id = "123" MATCH path = (m)-[*1..1]->(n) RETURN m
This very nearly works, however it still returns the central node (i.e. node n). How would I exclude this node from my query result?
[UPDATED]
This will return all distinct nodes directly connected to the specified node, and explicitly prevents the specified node from being returned (in case it has a relationship to itself):
MATCH (n:Node)--(m)
WHERE n.id = "123" AND n <> m
RETURN DISTINCT m;
Ideally I would have liked to match the nodes as mentioned in my question and delete them. However, as I have not found a way to do so an inverse approach can be utilised whereby all nodes but those as mentioned in the question are matched instead. Thereby effectively excluding (but not deleting) the unwanted nodes.
This can be achieved using this query:
MATCH (n:Node) WHERE n.id = "123" MATCH path = (m)-[*2..]->(n) RETURN path
This returns the central node and all paths to that node that have a "length" greater than or equal to 2.

Neo4j cypher query to see whether given nodes are connected

Given the following nodes B,E,F,G,H,J,K. I have to write a neo4j query to check how these nodes are connected each other.
For example, suppose this is the pattern I want to display.
B-H-F
|
G-J-K-E
What is the query to display this graph? I don't want to display all other nodes which are connected to these nodes.
You need to find the paths between each pair of source nodes.
Make sure that each path consists of only those nodes that are included in the source set.
You can do this with a cypher:
WITH {GIVEN_NODES} as NDS // The source array of node IDs
UNWIND RANGE(0, size(NDS)-2) as i
UNWIND RANGE(i+1, size(NDS)-1) as j
WITH NDS,
NDS[i] as N1,
NDS[j] as N2
MATCH path = (N1)-[*]-(N2)
WHERE length(path)+1 <= size(NDS) AND
ALL(n in nodes(path) WHERE n in NDS)
RETURN path

Resources