MongoDB query where array length is greater than ‘n’

While working on any project where we may have a requirement to check the size of an array or to get an element whose size is greater or less than a certain length. There are various ways to achieve this requirement with many MongoDB operators like $size, $where, $exists, etc.

The below method can help you to resolve your issue related to array length or checking the size of the array.

Sample Data

db.inventory.insertMany([
    { item: "journal", qty: 25, tags: ["blank", "red"], book: { author:'xyz', price:50, location:['india', 'usa', 'nepal']} },
    { item: "notebook", qty: 50, tags: ["red", "blank"], book: { author:'xyz', price:50, location:['india', 'usa']} },
    { item: "paper", qty: 100, tags: ["red", "blank", "plain"], book: { author:'xyz', price:50, location:[]}},
    { item: "planner", qty: 75, tags: ["blank", "red"], book: { author:'xyz', price:50, location:['india']} },
    { item: "postcard", qty: 45, tags: ["blue"], book:{} }
]);

1. $size (to get exact length of array)

{ field: { $size: n } }; // n is any integer

The $size operator matches any array with the number of elements specified by the argument.

$size does not accept ranges of values.

Example

  1. Find elements where tags length is 1
db.inventory.find({tags:{$size:1}})
//output
[{ item: "postcard", qty: 45, tags: ["blue"], book:{} }]

2. Find elements where books location length is 1

db.inventory.find({books.loction:{$size:1}}
//output
[{ item: "planner", qty: 75, tags: ["blank", "red"], book: { author:'xyz', price:50, location:['india']} }]

2. $where

Use the $where operator to pass either a string containing a JavaScript expression or a full JavaScript function to the query system

$where evaluates JavaScript and cannot take advantage of indexes.

Example:

  1. Find elements where tags length is 1
db.inventory.find({tags:{$where:'this.tags.length == 1'}}
//output 
[{ item: "postcard", qty: 45, tags: ["blue"], book:{} }] 

2. Find elements where tags length is greater or equal to 1

db.inventory.find({tags:{$where:'this.tags.length >= 1'}}

3. Find elements where books location length is 1

we cannot check this with the help of $where operator

Only apply the $where query operator to top-level documents. The $where query operator will not work inside a nested document.

3. dot notation

MongoDB uses the dot notation to access the elements of an array and to access the fields of an embedded document.

"<array>.<index>"

Examples:

  1. Find elements where tags length greater than 0
db.inventory.find({tags.0:{$exists:true'}}
// It will search all elements whose tags has atleast one element
// array is zero base index

2. Find elements where books.location length greater than 1

db.inventory.find({'book.location.1':{$exists:true'}}
// It will search all elements whose book.location has atleast two element.

4. $expr (3.6+)

{ $expr: { <expression> } }

Example:

  1. Find the document where tags length greater than 0
db.invantory.find({
    $expr: {
        $gt: [{ $size: { $ifNull: ["$tags", []] } }, 0]
    }
})

2. Find elements where books.location length greater than 1

db.invantory.find({
    $expr: {
        $gt: [{ $size: { $ifNull: ["$book.location", []] } }, 1]
    }
})
// $ifNull: ["$book.location", []] this is used to avoid any error if book.location is null

5. Aggregation $facet operator:

db.inantory.aggregate([
    {
        $facet: {
            "Total": [
                { $match: { 'tags.0': { $exists: true } } },
                { $count: "Total" }
            ]
        }
    },
    {
        $project: {
            "Total": { "$arrayElemAt": ["$Total.Total", 0] },
        }
    }
])
  • Find elements where books.location length greater than 1
db.inantory.aggregate([
    {
        $facet: {
            "Total": [
                { $match: { 'books.location.0': { $exists: true } } },
                { $count: "Total" }
            ]
        }
    },
    {
        $project: {
            "Total": { "$arrayElemAt": ["$Total.Total", 0] },
        }
    }
])

Leave a Reply