MongoDB $elemMatch Query Operator

When handling a large database, we generally use operators like $match and $filter to filter selections. However, MongoDB provides a more powerful operator called $elemMatch that can query arrays and embedded documents. Using $elemMatch, we can match specific conditions within an array or an embedded document, making our queries more precise and easily read. Let’s learn about $elemMatch in detail.

Other famous query operators are $gt and $lt, click here to read about them.

MongoDB $elemMatch Operator

The $elemMatch operator matches only those documents where at least one element in an array field meets the specified query criteria. We can pass multiple conditions for array elements to filter the selection.

Syntax:

db.collection.find({ field: { $elemMatch: { <query1>, <query2>, ... } } })

Parameters:

  • collection: The name of the collection in which we are searching for documents.
  • find: The method used to perform the query on the documents.
  • field: The name of the array field within the documents that we are querying. This specifies which array is being used for the search conditions.
  • <query1>, <query2>, …: The conditions or criteria used to filter the array elements. These should be in the form of key-value pairs.

Return:

It returns documents where at least one element of the array matches the given condition.

MongoDB doesn’t allow you to use the $where operator and the $text operator with the $elemMatch query operator.

Querying Arrays Using MongoDB $elemMatch

Let’s now use the MongoDB $elemMatch to select documents having an array field that satisfies all specified conditions.

First, choose a database to get started with:

use testGrades

Below are the documents in this database collection:

> db.grades.find({})

{ _id: 1, name: "John Mendes", grades: [ 82, 85, 88, 90, 78 ] }

{ _id: 2, name: "Sofia Derulo", grades: [ 70, 75, 68, 65, 70 ] }

{ _id: 3, name: "Areesha Shaikh", grades: [ 86, 89, 93, 90, 88 ] }

{ _id: 4, name: "Grace Handles", grades: [ 55, 65, 63, 68, 70 ] }

{ _id: 5, name: "Rebecca Chism", grades: [ 82, 78, 80, 91, 75 ] }

{ _id: 6, name: "David Hudson", grades: [ 67, 70, 78, 74, 72 ] }

{ _id: 7, name: "Latonya Jacobson", grades: [ 80, 87, 84, 95, 81 ] }

{ _id: 8, name: "Luigi Markham", grades: [ 82, 73, 79, 80, 71 ] }

Let’s use the $elemMatch to match values in the “grades” array to find out the nerds of the class:

db.grades.find( { grades: { $elemMatch: { $gte: 86, $lt: 100 } } } )

{ _id: 1, name: "John Mendes", grades: [ 82, 85, 88, 90, 78 ] }

{ _id: 3, name: "Areesha Shaikh", grades: [ 86, 89, 93, 90, 88 ] }

{ _id: 7, name: "Latonya Jacobson", grades: [ 80, 87, 84, 95, 81 ] }

In the above MongoDB query, “$gte: 86” specifies that the value must be greater than or equal to 86 and “$lt: 100” specifies that the value must be less than 100 and that’s what we got.

Querying Embedded Documents Using MongoDB $elemMatch

Additionally, we can use the $elemMatch query operator to match values within embedded documents.

Here’s what our sample data looks like:

{
        "_id" : ObjectId("5285bd678154c4747b705b4f"),
        "item_code" : "I001",
        "category" : [
                "boy",
                "girl"
        ],
        "description" : [
                {
                        "agegroup" : "3-5",
                        "flavour" : "chocolate",
                        "price" : 5
                },
                {
                        "agegroup" : "6-9",
                        "flavour" : "strawberry",
                        "price" : 6
                },
                {
                        "agegroup" : "10-13",
                        "flavour" : "mango",
                        "price" : 7
                }
        ]
}
{
        "_id" : ObjectId("5285bd808154c4747b705b50"),
        "item_code" : "I002",
        "category" : [
                "boy",
                "girl"
        ],
        "description" : [
                {
                        "agegroup" : "3-5",
                        "flavour" : "vanilla",
                        "price" : 3
                },
                {
                        "agegroup" : "6-9",
                        "flavour" : "lemon",
                        "price" : 6
                },
                {
                        "agegroup" : "10-13",
                        "flavour" : "mango",
                        "price" : 5
                }
        ]
}
{
        "_id" : ObjectId("5285bd8a8154c4747b705b51"),
        "item_code" : "I003",
        "category" : [
                "boy",
                "girl"
        ],
        "description" : [
                {
                        "agegroup" : "3-5",
                        "flavour" : "pineapple",
                        "price" : 5
                },
                {
                        "agegroup" : "6-9",
                        "flavour" : "mango",
                        "price" : 6
                },
                {
                        "agegroup" : "10-13",
                        "flavour" : "vanilla",
                        "price" : 5
                }
        ]
}

Now, let’s try to filter documents based on the “description” field, which contains an array of embedded documents.

Using the $elemMatch with multiple criteria on array will return the following document:

> db.table1.find( { "description": { $elemMatch: { "agegroup" : "3-5","price" : 5}}}).pretty();

{
        "_id" : ObjectId("5285bd678154c4747b705b4f"),
        "item_code" : "I001",
        "category" : [
                "boy",
                "girl"
        ],
        "description" : [
                {
                        "agegroup" : "3-5",
                        "flavour" : "chocolate",
                        "price" : 5
                },
                {
                        "agegroup" : "6-9",
                        "flavour" : "strawberry",
                        "price" : 6
                },
                {
                        "agegroup" : "10-13",
                        "flavour" : "mango",
                        "price" : 7
                }
        ]
}
{
        "_id" : ObjectId("5285bd8a8154c4747b705b51"),
        "item_code" : "I003",
        "category" : [
                "boy",
                "girl"
        ],
        "description" : [
                {
                        "agegroup" : "3-5",
                        "flavour" : "pineapple",
                        "price" : 5
                },
                {
                        "agegroup" : "6-9",
                        "flavour" : "mango",
                        "price" : 6
                },
                {
                        "agegroup" : "10-13",
                        "flavour" : "vanilla",
                        "price" : 5
                }
        ]
}

We got the documents whose array matched the specified multiple fields.

Want to learn about $each? Click here to read our dedicated article on it.

Conclusion

The $elemMatch operator is used when there is a need to filter multiple documents where at least one array element satisfies all specified queries. It is mostly used for finding documents where a single array element meets multiple criteria and we demonstrated examples of that as well. This operator is very useful but difficult to understand for beginners. So if you want an alternative, you can read our article on the $in operator.

Reference

$elemMatch (query) — MongoDB Manual

Aneesha S
Aneesha S
Articles: 171