Using Cypher, how can I find a node where a property doesn't exist?
For example, I have two nodes:
A = {foo: true, name: 'A'}, B = { name: 'B'}
Now I'd like to find B, selecting it on the basis of not having the foo property set. How can I do this?
As Michael Hunger mentioned
MATCH (n) WHERE NOT EXISTS(n.foo) RETURN n
On older versions of Neo4j you can use HAS:
# Causes error with later versions of Neo4j
MATCH (n) WHERE NOT HAS(n.foo) RETURN n
As of version 4.3 EXISTS has been deprecated on properties and instead, you should use IS NOT NULL.
So for the example in your question your query would now be:
MATCH (n) WHERE n.foo IS NULL RETURN n
MATCH (f) WHERE f.foo IS NULL RETURN f
Related
Beginner question. How do I get the distinct types of edge in Cypher?
I know how to get all the edges in the database:
MATCH (a)-[r*1..1]->(b)
RETURN extract(x IN r | {rel: x})
And I can see that each one has a TYPE property. But how do I refine this to get the distinct TYPEs?
i think this is what you are looking for
MATCH (a)-[r]->(b)
RETURN distinct(type(r))
you might also use
call db.relationshipTypes
edit: if the first doesnt return anything that means you have no relationship in db, second might work only from neo4j 3.1 version on
For any length paths you can use UNWIND and DISTINCT:
MATCH p = (a)-[r*1..5]->(b)
UNWIND relationships(p) as rel
RETURN distinct type(rel) as type
The builtin procedure db.relationshipTypes will return a collection of all relationship types very quickly, from cached data. For example:
CALL db.relationshipTypes() YIELD relationshipType
RETURN relationshipType;
Prior to version 3.0.0-M05, this procedure was named sys.db.relationshipTypes.
In Cypher is there a way to match nodes exactly, i.e. match where the existing node contains only the properties queried for?
For example if we have the following nodes:
CREATE (n {field1: 'value1'})
CREATE (n {field1: 'value1', field2: 'value2'})
And match:
MATCH (n {field1: 'value1'}) RETURN (n)
This will return the both nodes. However, I want the second node to be excluded because it also contains field2 which is not in the set of queried properties
One way to do this is to use the properties function, i.e.
MATCH (n) WHERE properties(n) = {field1: 'value1'} RETURN (n)
But would be good to know whether there are other/better ways
I have modified the 'vanilla' initial query in this console, and added one relationship type 'LOCKED' between the 'Morpheus' and 'Cypher' nodes.
How can I modify the existing (first-run) query, which is a variable length path so that it no longer reaches the Agent Smith node due to the additional Locked relationship I've added?
First-run query:
MATCH (n:Crew)-[r:KNOWS|LOVES*2..4]->m
WHERE n.name='Neo'
RETURN n AS Neo,r,m
I have tried this kind of thing:
MATCH p=(n:Crew)-[r:KNOWS|LOVES*2..4]->m
WHERE n.name='Neo'
AND none(rel IN rels(p) WHERE EXISTS (StartNode(rel)-[:LOCKED]->EndNode(rel)))
RETURN n AS Neo,r,m
..but it doesn't recognize the pattern inside the none() function.
I'm using Community 2.2.1
Thanks for reading
I'm pretty sure you can't use a function in a MATCHy type clause like that (though it's clever). What about this?
MATCH path=(neo:Crew)-[r:KNOWS|LOVES|LOCKED*2..4]->m
WHERE neo.name='Neo'
AND NOT('LOCKED' IN rels(path))
RETURN neo,r,m
EDIT:
Oops, looks like Dave might have beat me to the punch. Here's the solution I came up with anyway ;)
MATCH p=(neo:Crew)-[r:KNOWS|LOVES*2..4]->m
WHERE neo.name='Neo'
WITH p, neo, m
UNWIND rels(p) AS rel
MATCH (a)-[rel]->(b)
OPTIONAL MATCH a-[locked_rel:LOCKED]->b
WITH neo, m, collect(locked_rel) AS locked_rels
WHERE none(locked_rel IN locked_rels WHERE ()-[locked_rel]->())
RETURN neo, m
Ok, this is a little convoluted but i think it works. The approach is to take all of the paths and find the last known good nodes (ones that have LOCKED relationships leaving them). Then use that node(s) as a new ending point(s) and return the paths.
match p=(n:Crew)-[r:KNOWS|LOVES|LOCKED*2..4]->m
where n.name='Neo'
with n, relationships(p) as rels
unwind rels as r
with n
, case
when type(r) = 'LOCKED' then startNode(r)
else null
end as last_good_node
with n
, (collect( distinct last_good_node)) as last_good_nodes
unwind last_good_nodes as g
match p=n-[r:KNOWS|LOVES*]->g
return p
I think this would be simpler if there was a locked: true property on the KNOWS and LOVES relationships.
query:
Match (d:User {name:"User"}) -[r:IS_MEMBER_OF]->(g:Group:Local) - [r1:IS_SUBGROUP_OF*0..]->(g1:Group) Return type(r), type(r1)
the cypher command type is valid for the relation without variable length paths but not valid for the variable ones even when they have the same name. How would I grab the name (type) of r1 as return from the query?
Thanks,
B
Unfortunately, there seems to be a bug in version 2.2.1 (and maybe some earlier versions) that prevents this from working:
MATCH (:User { name:"User" })-[r:IS_MEMBER_OF]->(:Group:Local)-[r1:IS_SUBGROUP_OF*0..]->(:Group)
RETURN type(r), EXTRACT(rel IN r1 | type(rel)) AS ancestorGroupTypes;
So, this is a workaround until the above simpler query works again:
MATCH p=(:User {name:"User"})-[r:IS_MEMBER_OF]->(:Group:Local)-[r1:IS_SUBGROUP_OF*0..]->(:Group)
Return type(r), EXTRACT (rel IN TAIL(RELATIONSHIPS(p)) | type(rel)) AS ancestorGroupTypes;
How can I show all nodes and relationships in Data Browser tab?
What are sample index queries that I can type in in search field?
You may also want to try a cypher query such as:
START n=node(*) RETURN n;
It's very obvious, and it will return all the existing nodes in the database.
EDIT : the following displays the nodes and the relationships :
START n=node(*) MATCH (n)-[r]->(m) RETURN n,r,m;
More simple way is
MATCH (n) RETURN (n)
MATCH (n) OPTIONAL MATCH (n)-[r]-() RETURN n, r;
You can show everything with simple MATCH (n) RETURN n, as offical documentation suggests.
START n=node(*) RETURN n from Neo4j 2.0 is deprecated:
The START clause should only be used when accessing legacy indexes
(see Chapter 34, Legacy Indexing). In all other cases, use MATCH
instead (see Section 10.1, “Match”).
There is a little help icon beside the search field, if you hoover over it it shows the syntax.
If a property of your nodes and relationships is indexed you can search for all of them like this.
node:index:indexname:fieldname:*
rels:index:indexname:fieldname:*
I found that this worked, retrieving all nodes including orphans, and all relationships:
MATCH (n) MATCH ()-[r]->() RETURN n, r
Other good way for get ALL nodes (and nodes without relationship) :
MATCH (n) RETURN n UNION START n = rel(*) return n;