Excluding label names in simple Neo4j Query - neo4j

Usually I can find everything I need already on SO but not this time. I'm looking for a very simple way to exclude labels, for example (pseudo code):
match (n) where n not in (Label1, Label2) return n
Sorry about crappy query. In short I have labels x,y,z and I want to return all of them apart from z.
Thnx!

This should do it:
MATCH (n)
WHERE NOT n:Label1 AND NOT n:Label2
RETURN n;

If you have a long list of labels you want to exclude, I find this syntax to be helpful:
match (n)
where not labels(n) in [['label1'],['label2'],['label3']]

Related

In neo4j how to return specific nodes or relationship with cypher?

You are given two arrays one for some labels and another for some relationships and you are asked to return the nodes and their relationships which are found only in the arrays you where given. I tried different approach to it but I couldn't get a better cipher to return the graph with respect to both arrays
MATCH (n)-[r]-(m) where n in ["username"] and r in ["knows"] return n,r
The code above, I know its completely wrong but it kinda shows the idea, share your thoughts 😁
This should work:
MATCH (n)-[r]-(m)
WHERE ANY(l IN labels(n) WHERE l IN ['username','label2'])
AND type(r) IN ['knows','relType2']
RETURN n,r,m

match a branching path of variable length

I have a graph which looks like this:
Here is the link to the graph in the neo4j console:
http://console.neo4j.org/?id=av3001
Basically, you have two branching paths, of variable length. I want to match the two paths between orange node and yellow nodes. I want to return one row of data for each path, including all traversed nodes. I also want to be able to include different WHERE clauses on different intermediate nodes.
At the end, i need to have a table of data, like this:
a - b - c - d
neo - morpheus - null - leo
neo - morpheus - trinity - cypher
How could i do that?
I have tried using OPTIONAL MATCH, but i can't get the two rows separately.
I have tried using variable length path, which returns the two paths but doesn't allow me to access and filter intermediate nodes. Plus it returns a list, and not a table of data.
I've seen this question:
Cypher - matching two different possible paths and return both
It's on the same subject but the example is very complex, a more generic solution to this simpler problem is what i'm looking for.
You can define what your end node by using WHERE statement. So in your case end node has no outgoing relationship. Not sure why you expect a null on return as you said neo - morpheus - null - leo
MATCH p=(n:Person{name:"Neo"})-[*]->(end) where not (end)-->()
RETURN extract(x IN nodes(p) | x.name)
Edit:
may not the the best option as I am not sure how to do this programmatically. If I use UNWIND I get back only one row. So this is a dummy solution
MATCH p=(n{name:"Neo"})-[*]->(end) where not (end)-->()
with nodes(p) as list
return list[0].name,list[1].name,list[2].name,list[3].name
You can use Cypher to match a path like this MATCH p=(:a)-[*]->(:d) RETURN p, and p will be a list of nodes/relationships in the path in the order it was traversed. You can apply WHERE to filter the path just like with node matching, and apply any list functions you need to it.
I will add these examples too
// Where on path
MATCH p=(:a)-[*]-(:d) WHERE NONE(n in NODES(p) WHERE n.name="Trinity") WITH NODES(p) as p RETURN p[0], p[1], p[2], p[3]
// Spit path into columns
MATCH p=(:a)-[*]-(:d) WITH NODES(p) as p RETURN p[0], p[1], p[2], p[3]
// Match path, filter on label
MATCH p=(:a)-[*]-(:d) WITH NODES(p) as p RETURN FILTER(n in p WHERE "a" in LABELS(n)) as a, FILTER(n in p WHERE "b" in LABELS(n)) as b, FILTER(n in p WHERE "c" in LABELS(n)) as c, FILTER(n in p WHERE "d" in LABELS(n)) as d
Unfortunately, you HAVE to explicitly set some logic for each column. You can't make dynamic columns (that I know of). In your table example, what is the rule for which column gets 'null'? In the last example, I set each column to be the set of nodes of a label.
I.m.o. you're asking for extensive post-processing of the results of a simply query (give me all the paths starting from Neo). I say this because :
You state you need to be able to specify specific WHERE clauses for each path (but you don't specify which clauses for which path ... indicating this might be a dynamic thing ?)
You don't know the size of the longest path beforehand ... but you still want the result to be a same-size-for-all-results table. And would any null columns then always be just before the end node ? Why (for that makes no real sense other then convenience) ?
...
Therefore (and again i.m.o.) you need to process the results in a (Java or whatever you prefer) program. There you'll have full control over the resultset and be able to slice and dice as you wish. Cypher (exactly like SQL in fact) can only do so much and it seems that you're going beyond that.
Hope this helps,
Regards,
Tom
P.S. This may seem like an easy opt-out, but look at how simple your query is as compared to the constructs that have to be wrought trying to answer your logic. So ... separate the concerns.

Neo4J, Match node with "OR"

Helo,
i want to match a graph where a node can be typeX or typeY
my first thought was:
match (:typeX|typeY)-[]-(z) return z
But this doesn´t work :(
Is there any way without typing the query twice?
Like this:
match (:typeX)-[]-(z), (:typeY)-[]-(z) return z
Can someone help me?
thank you in advance :)
One way is
MATCH (n) WHERE labels(n) IN ['typeX','typeY']
WITH n
MATCH (n)-[]-(z)
RETURN z
However, if "either typeX or typeY" are queried frequently and share some common purpose in your domain, you could add another common label to them like "commonXY" and query using that label instead.
Unfortunately there's not a good efficient way to do this without sacrificing performance. All other current answers are forced to scan all nodes and then filter on their labels, which isn't performant with large numbers of nodes (PROFILE the queries). All the efficient means I know of are more verbose.
You can perform a UNION of the two queries to return nodes one hop from all :typeX and :typeY nodes.
match (:typeX)--(z)
return z
union
match (:typeY)--(z)
return z
This query will work even if n has multiple labels:
MATCH (n)
WHERE ANY(lab IN labels(n) WHERE lab IN ['typeX', 'typeY'])
MATCH (n)--(z)
RETURN z
there is a n predicate n:Label
MATCH (n)--(z)
WHERE n:typeX OR n:typeY
RETURN z

Neo4j Match multiple labels

There is the situation in which i need to match any one of the label of node.
We can do it for relationship types like
(n)-[:KNOWS|LOVES]->(m)
Can we match node labels like this?
eg.
MATCH (c:computer)<-[:belongs_to]-(comp:HP|IBM)
return comp
Currently I have tried this and it gives results, Is there any simpler way?
MATCH (c:computer)<-[:belongs_to]-(comp)
WHERE 'HP' IN labels(comp) OR 'IBM' IN labels(comp)
return comp
I Think
WHERE 'HP' IN labels(comp) OR 'IBM' IN labels(comp)
AND
WHERE comp:HP OR comp:IBM
Will work with same manner second one is simple to use
This form of your last query is at least simpler to write and more easily understood:
MATCH (c:computer)<-[:belongs_to]-(comp)
WHERE comp:HP OR comp:IBM
return comp;
Currently facing this same problem.
Since I have quite a few labels to match on (revealing a bit of a flaw in my architecture!) I found the following to solve this problem concisely:
MATCH (n:computer)
WHERE any(label in labels(n) WHERE label in ['HP', 'IBM'])
RETURN n

Match several node property values in Cypher / Neo4J

using Cypher 2 I want to find all the nodes of a certain label (Context), which are called either "health" or "opinion".
The query that works is:
MATCH (c:Context) WHERE c.name="health" OR c.name="opinion" RETURN c;
But I'm wondering if Cypher has a syntax that I could put it into the first MATCH part, something like this:
MATCH (c:Context{name:"health"|name:"opinion})
The example above doesn't work, but I'm just showing it to let you know what I mean.
Thank you!
Alternatively, you can do this:
MATCH (c:Context) WHERE c.name IN ['health', 'opinion'] RETURN c
Still not in the "MATCH" statement, but a little easier as your list of possible values grows.
You could do
MATCH (c:Context {name:"health"}), (d:Context { name:"opinion"})
RETURN c,d

Resources