alyx
alyx

Reputation: 2733

Neo4j: WHERE NOT is returning incorrect nodes

When running this query:

MATCH (profile:Profile)
MATCH (profile)-[:INTERACTION]->(i)
WHERE NOT 'foo' IN i.content
RETURN DISTINCT profile

Neo is returning profile nodes with :INTERACTION relationships that have i.content = foo even though I stated WHERE NOT.

INTERACTION node structure looks like:

[{
  "content": String
}]

Am I missing a step?

Upvotes: 0

Views: 25

Answers (2)

InverseFalcon
InverseFalcon

Reputation: 30397

I think you haven't quite defined what you want clearly in the query.

You asked for :Profile nodes that have an :Interaction relationship to a node without 'foo' in its content property.

This is completely different than asking for :Profile nodes that do not have any relationship to a node with 'foo' in its content property.

There are a few ways to get what you want

MATCH (profile:Profile)
OPTIONAL MATCH (profile)-[:INTERACTION]->(i)
WHERE 'foo' IN i.content
WITH profile
WHERE i IS NULL
RETURN profile

or

MATCH (profile:Profile)
WITH profile,  [(profile)-[:INTERACTION]->(i) WHERE 'foo' IN i.content | i] as fooInteractions
WHERE size(fooInteractions) = 0
RETURN profile

Also as cybersam noted you're using the IN keyword which is for membership checking in a list, but you've stated you have values like i.content = 'foo' so you may be misusing this.

If so then this would make the correct query much simpler than those ones above:

MATCH (profile:Profile)
WHERE NOT (profile)-[:INTERACTION]->(i {content:'foo'})
RETURN profile

And as cybersam also noted your wording suggests that maybe you actually want to check the content property of the :INTERACTION relationship. If this is really what you want, then move the {content:'foo'} over to the :INTERACTION relationship in the pattern instead.

Upvotes: 1

cybersam
cybersam

Reputation: 66999

The IN keyword is only used to test if a value is a member of a list. For example: 5 IN [1,2,3].

To test for inclusion in a string, there are several options. One option is to use the CONTAINS keyword; for example: i.content CONTAINS 'foo'.

NOTE: In your query, i is the variable for a node, not a relationship. Are you actually trying to test the relationship's content property? Please correct your question, as you currently seem to be using the terms "node" and "relationship" interchangeably.

Upvotes: 1

Related Questions