Neo4j Cypher: Find isolated node - neo4j

I want to find nodes that do not connect with other nodes. (node A and node B in the picture below)
What I have tried is
MATCH (n:node) WHERE not ((n)<-[:connect]->(:node)) RETURN n
which seems to return only B.
How can I retrieve both A and B?
Thank you in advance!

[UPDATED]
This will work if you only care about connect relationships:
MATCH (n:node)
WHERE SIZE([(n)-[:connect]-(m:node) WHERE n <> m|1]) = 0
RETURN n
But if you want to pay attention to all relationship types, then use this:
MATCH (n:node)
WHERE SIZE([(n)--(m:node) WHERE n <> m|1]) = 0
RETURN n

Related

Query to write hops and return all the properties from the middle nodes or a better way to do it and skip hops?

Node A is connected to Node E through different nodes B (B can be repeating), C and D etc as given below.
(A)--(C)--(D)--(E)
(A)--(B)--(C)--(D)--(E)
(A)--(B)--(B)--(C)--(D)--(E)
(A)--(B)--(B)--(B)--(C)--(D)--(E)
There could be up to 7 B nodes between A and C or no B node at all (like the first case above).
Question: How to get all the E1, E2, E3, E4 connected to A1 with a single query and return properties from all A, B, C, D and E nodes? I could not return the properties using the hops.
MATCH (A {Id:30})-[*1..6]-(E) RETURN DISTINCT A.Name, E.Name;
But we want to return B.Name (If there are multiple B nodes in the middle their names too), C.Name and D.Name too. Happy to skip hopping completely if required. Help please? Thanks in advance.
Try this
// in case there is always A,C and E, you can look for
// paths with length 3 to 6
MATCH path=(A)-[*3..6]-(E)
// return the name of each node in the same order
RETURN [n IN nodes(path) | n.name] AS nodeNames
Assuming A through E are node labels, this query should get all paths that match your pattern (with 0 to 7 B nodes between the A and C nodes), and return distinct lists of node Name values:
MATCH p=(:A)-[*..8]-(:C)--(:D)--(:E)
WHERE ALL(n IN NODES(p)[1..-3] WHERE 'B' IN LABELS(n))
RETURN DISTINCT [m IN NODES(p) | m.Name] AS names
In general, the query would be more efficient if you could also specify the relationship types and their directionality.

Neo4j more efficient Cypher query for finding connected nodes with a relationship

I have a patch where I know a starting and end node with an unknown number of nodes between the 2. I wish to collect a collection of nodes and each nodes exiting relationship in the chain.
PROFILE MATCH p = (:Question{id:'1234'})-[:Answer*0..3]->(t)-
[:Answer]->(:Question{id:'5678'})
WHERE t:Set OR t:Read
OPTIONAL MATCH (x)-[v:Answer]->(y)
WHERE x.id <> '1234' and x IN nodes(p) AND v IN rels(p)
return x,v
This query is pretty inefficient as the OPTIONAL MATCH (x)-[v:Answer]->(y) requires a full nodes scan.
I know that t and as a result x will be of types Set or Read which would reduce the scan quite a bit but don't think there is a way to query this.
Is there any way to optimise this?
You can simply unwind the path you have already got:
MATCH p = (:Question{id:'1234'})-[:Answer*0..3]->(t)-[:Answer]->(:Question{id:'5678'})
WHERE t:Set OR t:Read
WITH nodes(p) AS nds,
rels(p) AS rls
UNWIND range(1, length(nds)-2) AS i
RETURN nds[i] AS x,
rls[i] AS v

How do I write this Neo4j Query?

There are three node types: A, B and C.
I need all the A's and B's and only the C's that participate in exactly one relationship.
match (n)
where n:A or n:B or (n:C)-[]-()
with count(n) as countOfRels
where countOfRels > 0
return n
Not close, I know. I'm not sure where to go from here.
It's a bit strange that A, B and C do not seem to be related ... but here's how you could solve your question for C :
MATCH (n:C)
WHERE size((n)-[]-()) = 1
RETURN n
UNION
MATCH (n:A)
RETURN n
UNION
MATCH (n:B)
RETURN n;
Hope this helps.
Regards,
Tom
you can use this
match(n)
where n:A OR n:B OR (n:C)-[r]-()
with count(r) as countOfRels
where countOfRels > 0
return n
Hope this helps.
You can do MATCH (a)--() WHERE NOT ()--(a)--() to match "nodes with only one relation". After that, You can use UNION or COLLECT()+UNWIND to combine the separate queries into one row result set.
// using Union
MATCH (n:C)--()
WHERE NOT ()--(n)--()
RETURN n
UNION
MATCH (n:A)
RETURN n
UNION
MATCH (n:B)
RETURN n;
// Using collect
OPTIONAL MATCH (a:A)
OPTIONAL MATCH (b:B)
OPTIONAL MATCH (c:C)--() WHERE NOT ()--(c)--()
WITH COLLECT(a)+COLLECT(b)+COLLECT(c) as nodez
UNWIND nodez as n
RETURN DISTINCT n

cypher multiple match is very slow

I want to match some node which don't satisfy the condition, but it's very slow. How to optimize it? There are about 70000 nodes in the database.
match (n:A)--(p:B)--(q:C)
with collect(n) as nc
match m where not m in nc
return count(m)
There is no need to first get all the nodes that match an initial pattern. It is enough to go through all the nodes and check them:
MATCH (m) WHERE NOT (m)--(:B)--(:C)
RETURN count(m)
Or if the condition on the label 'A' is important:
MATCH (m)
OPTIONAL MATCH p = (m)--(:B)--(:C)
WITH m WHERE (p IS NULL) OR (NOT p IS NULL AND NOT 'A' IN LABELS(m))
RETURN count(m)

cypher return twice for nodes that connected in bi-directional relationship

I have 2 nodes: (A), (B), connected by [:FRIEND]
When I run the following command,
start n = node(*) match (n)-[r:FRIEND]-(b) return n.name, b.name;
it returns 2 rows:
A, B and B, A.
I wonder, how to make it return only one record, because the relationship is bidirectional, A -[:FRIEND]-B and B-[:FRIEND]-A is considered same result.
Thanks.
One trick is to add a where on the IDs, so you get them in a consistent order as well:
start n = node(*)
match (n)-[r:FRIEND]-(b)
where id(n) < id(b)
return n.name, b.name;
http://console.neo4j.org/r/1ry0ga
If you have multiple relationships between them (in both directions, for example), you can add a distinct modifier to get the same results:
start n = node(*)
match (n)-[r:FRIEND]-(b)
where id(n) < id(b)
return distinct n.name, b.name;

Resources