BoumTAC
BoumTAC

Reputation: 3781

mongodb find with opposite of $elemMatch

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

Answers (3)

devGrammer
devGrammer

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

Ramit Mittal
Ramit Mittal

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

Blakes Seven
Blakes Seven

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

Related Questions