Reputation: 3781
I have a collection like this:
posts = {
title: 'Hey',
content: '...',
authors: [{
id: 'id',
name: 'John'
}, {
id: 'id2',
name: 'david'
}]
};
I want to make a query. I have found the $elementMatch, but I would like the opposite.
I have also found $nin but I don't if it works for mycase.
Here is what I want to do:
db.posts.find({
authors: {
$notElemMatch: {
id: 'id'
}
}
});
I want to find every posts except those writing by someone.
Upvotes: 4
Views: 3389
Reputation: 65
Here is a better way to "invert" the $elemMatch
operator with aggregation.
Use $expr
$eq
and $in
$in
checks if the item is in the array, since we want opposite meaning false
so we check if the result of the "$in" operation is $eq
(equal) to false
{
"$expr": {
"$eq": [{ "$in": { 'id', "authors.id"} }, false]
}
}
Upvotes: 1
Reputation: 573
While the original question does not require the use of $elemMatch
(as answered by Blakes), here is one way to "invert" the $elemMatch
operator.
Use $filter
+ $and
as a subsitute for $elemMatch
and check that the result has 0 length.
$expr
allows the use of aggregation expressions in simple "find" queries.
All conditions in $elemMatch
will be translated to items in the array supplied as an argument to $and
.
Tested to work with MongoDB server version 5.0.9
{
"$expr": {
"$eq": [
{
"$size": {
"$filter": {
"input": "$authors",
"cond": {
"$and": [
{
"$eq": ["$$this.id", "id"]
}
]
}
}
}
},
0
]
}
}
Upvotes: 2
Reputation: 50406
You don't even need $elemMatch
since you only have a single field condition. Just use $ne
instead:
db.posts.find({ "authors.id": { "$ne": 'id' } });
There is a $not
condition, but it really does not need apply here.
Upvotes: 10