2
votes

I am trying to write a neo4j query where I only want to present nodes that are have no relation to nodes with a specific property. One way to think of it is where two separate graphs exist where one node has the property I want to exclude. I should get a result that only contains the graph of the set of nodes not connected to the node that has the property I want to exclude. This is what the graph looks like before my query enter image description here

match (n) where not (n{property:'valueIWishToExclude'})--() return n

This is what the result of the query looks like enter image description here

I only want to have the four connected nodes in my results. How can I set up a query that excludes the nodes that are not connected to the node with the property I wish to exclude?

3

3 Answers

2
votes

In fact you need those nodes from which there is no path to the node that should be excluded. You can use the shortestPath function and ALL predicate:

match (ex) where n.property = 'valueIWishToExclude'
with collect(ex) as exn
match (n) where (not n.property = 'valueIWishToExclude') and
                ALL(e in exn where not shortestPath( (n)-[*]-(e) ) is null)
return n
1
votes

You are almost there, just add in the relationship in your query to only get the nodes that are related to each other

MATCH (n:label) -[:RELATED]->()  where n.property<>'exclude'
RETURN n

That should return only the nodes connected to each other, as the other nodes do not have that relationship.
Let me know if that worked for you.

1
votes

You may want to alter your wording a bit, what you're asking for in this question, and what you really want, are not the same thing.

In Neo4j (and most graph databases), the phrase "nodes that have no relation to..." means nodes that are not connected by a relationship to the node in question.

In that context, in your right graph (assuming the one node selected is the node marked as excluded), one node would fit the criteria and be returned as a possible result, the topmost node, since it doesn't have a relationship to the node you want to exclude; It is however two relationships removed from the excluded node.

You seem to be asking for something else, though. You seem to want nodes that are not in the same subgraph as the node to exclude. Or, alternately, nodes that have no path to the excluded node.

Make sure on future queries you're clear about what you're asking, or you'll get answers that have no relevance to what you really want.

One approach that will work is to first find all nodes within the subgraph of the excluded node, and then return all nodes that are not in those subgraph nodes.

You'll want to install APOC Procedures so you can make use of a fast means of obtaining nodes within the subgraph.

You'll also want to use labels in your graph, and maybe put an index on the property you're searching for as this will make your search fast. As it is now, your query must examine every node in your entire database to find nodes with the property in question, and that will become slower and slower as your graph grows.

Your query might look like this (using 'Label' as a stand-in for the node label):

MATCH (n:Label{propertyToExclude:'valueToExclude'})
CALL apoc.path.expandConfig(n, {bfs:true, uniqueness:"NODE_GLOBAL"}) YIELD path
WITH COLLECT(DISTINCT LAST(NODES(path))) as subgraph
MATCH (n)
WHERE NOT n in subgraph
RETURN n