[SERVER-4965] $not appears to distribute incorrectly over conjunctions Created: 14/Feb/12  Updated: 29/Feb/12  Resolved: 14/Feb/12

Status: Closed
Project: Core Server
Component/s: None
Affects Version/s: 2.0.0, 2.0.3
Fix Version/s: None

Type: Bug Priority: Minor - P4
Reporter: John R Assignee: Unassigned
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Related
related to DOCS-128 Document the behavior of $not applied... Closed
Operating System: ALL
Participants:

 Description   

The $not operator appears to incorrectly distribute over (implicit) conjunctions of operators like $in, $gt, etc.
It appears to treat "not(p and q)" as "not(p) and not(q)" instead of "not(p) or not(q)".
This has only been tested on db versions 2.0.0 and 2.0.3-rc0.

Examples:

// insert some data
db.test.insert(

{a:1}

)
db.test.insert(

{a:3}

)

// Example 1
// not(a > 2 and a < 4)
// a <= 2 or a >= 4
// should yield the row with a = 1
// instead it yields no rows, appearing to do:
// a <= 2 and a >= 4
db.test.find({a:{$not:{$gt:2, $lt:4}}})

// Example 2
// not(a < 2 and a > 4)
// a >= 2 or a <= 4
// should yield both rows (a = 1 and a = 3)
// instead it yields only a = 3, appearing to incorrectly distribute "$not" over the implicit conjunction to get:
// a >= 2 and a <= 4
db.test.find({a:{$not:{$lt:2, $gt:4}}})



 Comments   
Comment by Aaron Staple [ 14/Feb/12 ]

Also, feel free to file a new ticket requesting different behavior for $not.

Comment by Aaron Staple [ 14/Feb/12 ]

Yep, I already filed DOCS-128 to improve the documentation.

Btw, you can use $nor to get behavior similar to what you're looking for: {$nor:[{a:{$gt:2,$lt:4}}]}

Comment by John R [ 14/Feb/12 ]

It seems that many users would expect the query
db.test.find({a:{$not:{$gt:2, $lt:4}}})
to yield those documents that do not appear in the query
db.test.find({a:{$gt:2, $lt:4}})
as per ordinary logic / De Morgan's laws and the behavior of analogous expressions in SQL and other languages.
That behavior would certainly be useful in the case of a conjunction of operators.
I'm not sure in what situations it is useful to treat "not(p and q)" as "not(p) and not(q)", but if that usage makes sense, then it would certainly be helpful for it to be documented.

Comment by Aaron Staple [ 14/Feb/12 ]

This is the behavior that was designed for $not. $not is a meta operator - it just reverses the matching behavior of the operators in a sub object. It does not reverse the matching behavior of a conjunction of operators in a subobject.

Generated at Thu Feb 08 03:07:28 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.