Find documents with array that doesn't contains a specific value

I have the following model:

var PersonSchema = new Schema({
    name: String,
    groups: [
        {type: Schema.Types.ObjectId, ref: 'Group'}
    ],
});

I am looking for a query that retrieves all the Persons that are not part of a certain Group (i.e the persons’ group array doesn’t contain the id of the specified group).

I was thinking about something like this, but I’m not sure it is correct:

Person.find({groups: {$nin: [group._id]})

17 thoughts on “Find documents with array that doesn't contains a specific value”

  1. This is a better way to do this in Mongoose v5.11:

    Person.find({ occupation: /host/ }).where('groups').nin(['group1', 'group2']);
    

    The code becomes clearer and has more readability.

    Reply
  2. Nothing wrong with what you are basically attempting, but perhaps the only clarification here is the common misconception that you need operators like $nin or $in when querying an array.

    Also you really need to do here is a basic inequality match with $ne:

    Person.find({ "groups": { "$ne": group._id } })
    

    The “array” operators are not for “array targets” but for providing a “list” of conditions to test in a convenient form.

    Person.find({ "groups": { "$nin": [oneId, twoId,threeId] } })
    

    So just use normal operators for single conditions, and save $in and $nin for where you want to test more than one condition against either a single value or a list. So it’s just the other way around.

    If you do need to pass a “list” of arguments where “none” of those in the provided list match the contents of the array then you reverse the logic with the $not operator and the $all operator:

    Person.find({ "groups": { "$not": { "$all": [oneId,twoId,threeId] } } })
    

    So that means that “none of the list” provided are present in the array.

    Reply

Leave a Comment