How to query an array of subdocuments in MongoDB (with examples)

Updated: February 4, 2024 By: Guest Contributor Post a comment

Overview

Mastering the art of querying is a foundational skill for any MongoDB developer, especially when working with complex data structures such as arrays of subdocuments. MongoDB, as a NoSQL database, offers flexible document schemas enabling arrays of subdocuments to store related information. This tutorial walks you through various techniques to efficiently query arrays of subdocuments in MongoDB, from basic to advanced examples.

Let’s start with a simple document in a collection named users to illustrate our examples:

{
  "name": "John Doe",
  "age": 30,
  "addresses": [
    { "street": "123 Elm St", "city": "Springfield" },
    { "street": "456 Maple St", "city": "Shelbyville" }
  ]
}

Basic Queries

To begin, let’s explore some basic queries to understand how to access subdocuments.

Finding Documents with a Specific Subdocument

db.users.find({"addresses.street": "123 Elm St"})

This query will return all users living at “123 Elm St”. MongoDB uses dot notation to traverse subdocuments.

Matching an Exact Subdocument

db.users.find({"addresses": {"street": "123 Elm St", "city": "Springfield"}})

To match an exact subdocument, the entire document must be specified. Note that this query won’t return any results because MongoDB matches the entire array against the query.

Intermediate Queries

As we move to more advanced queries, let’s explore querying with $elemMatch.

Querying with $elemMatch

db.users.find({"addresses": {"$elemMatch": {"city": "Springfield", "street": {"$regex": "^123"}}}})

$elemMatch allows you to match subdocuments in an array that meet all the specified query criteria. This is particularly useful when you want to perform queries that must satisfy multiple conditions within a single subdocument.

Advanced Queries

Moving to more sophisticated techniques, we can manipulate and project arrays of subdocuments in ways that serve more complex application logic.

Projecting Specific Fields in Subdocuments

db.users.find({}, {"addresses.$": 1})

This query returns only the first subdocument in the “addresses” array that matches the query criteria. The $ operator is used for projection in this context.

Querying with Aggregation Pipeline

db.users.aggregate([
  {"$match": {"addresses.city": "Springfield"}},
  {"$unwind": "$addresses"},
  {"$match": {"addresses.street": "123 Elm St"}},
  {"$project": {"name": 1, "addresses": 1}}
])

Aggregation pipelines provide a powerful framework for data transformation and analysis. In this example, the $match and $unwind stages filter and flatten the “addresses” array, allowing for more granular querying and projection.

Conclusion

Querying arrays of subdocuments in MongoDB requires a solid understanding of querying principles and techniques. Starting with basic dot notation and advancing through $elemMatch, projection, and aggregation stages, developers can effectively navigate and manipulate complex data structures. Embracing MongoDB’s flexibility and depth will undoubtedly enhance your application’s data handling capabilities.