MongoDB Array Operators
Arrays are one of MongoDB's most powerful features, allowing you to store multiple values within a single document field. MongoDB provides a rich set of operators specifically designed to query, update, and manipulate array fields, making it easy to work with complex data structures.
Introduction to Array Operators
In MongoDB, array operators fall into two main categories:
- Query Operators - Used to search and filter documents based on array contents
- Update Operators - Used to modify array fields by adding, removing, or updating elements
Understanding these operators is essential for efficiently working with document databases, especially when dealing with nested data or collections where documents contain lists of items.
Query Array Operators
Query operators help you find documents based on array contents. Let's explore the most common ones:
$all - Match All Elements
The $all
operator selects documents where the array field contains all the specified elements, regardless of their order.
// Find all products that have both "wireless" and "bluetooth" in their tags array
db.products.find({ tags: { $all: ["wireless", "bluetooth"] } })
This query returns products that have both "wireless" and "bluetooth" tags, even if the array contains other tags as well.
$elemMatch - Match Elements with Multiple Criteria
The $elemMatch
operator matches documents that contain an array field with at least one element that matches all the specified query criteria.
// Find all students with at least one score between 80 and 90
db.students.find({
scores: {
$elemMatch: { $gte: 80, $lte: 90 }
}
})
Input Document:
{
name: "Alice",
scores: [75, 88, 92]
}
This document would match because it has a score (88) that falls between 80 and 90.
$size - Match Arrays by Length
The $size
operator selects documents where the array field has the specified number of elements.
// Find all users who have exactly 3 devices
db.users.find({ devices: { $size: 3 } })
Input Documents:
{ name: "John", devices: ["phone", "laptop", "tablet"] } // Match
{ name: "Mary", devices: ["phone", "laptop"] } // No match
Update Array Operators
Update operators modify array contents. These are used with the updateOne()
, updateMany()
, or findAndModify()
methods.
$push - Add Elements to an Array
The $push
operator adds an element to the end of an array.
// Add a new tag to a product
db.products.updateOne(
{ _id: ObjectId("5f8d2e3f2d7c2a1f4e8b4567") },
{ $push: { tags: "waterproof" } }
)
Before:
{
_id: ObjectId("5f8d2e3f2d7c2a1f4e8b4567"),
name: "Wireless Earbuds",
tags: ["wireless", "bluetooth", "audio"]
}
After:
{
_id: ObjectId("5f8d2e3f2d7c2a1f4e8b4567"),
name: "Wireless Earbuds",
tags: ["wireless", "bluetooth", "audio", "waterproof"]
}
$addToSet - Add Unique Elements
The $addToSet
operator adds an element to an array only if it doesn't already exist, ensuring uniqueness.
// Add "sports" category if not already present
db.products.updateOne(
{ _id: ObjectId("5f8d2e3f2d7c2a1f4e8b4568") },
{ $addToSet: { categories: "sports" } }
)
If "sports" is already in the categories array, the array remains unchanged.
Multiple Elements with each
To add multiple elements at once, combine $push
with the $each
modifier:
// Add multiple tags to a product
db.products.updateOne(
{ _id: ObjectId("5f8d2e3f2d7c2a1f4e8b4567") },
{
$push: {
tags: {
$each: ["portable", "lightweight", "rechargeable"]
}
}
}
)
$pull - Remove Elements
The $pull
operator removes all instances of a specified value from an array.
// Remove "discontinued" tag from all products
db.products.updateMany(
{},
{ $pull: { tags: "discontinued" } }
)
To remove elements that match multiple criteria, use query conditions:
// Remove all scores below 60
db.students.updateMany(
{},
{ $pull: { scores: { $lt: 60 } } }
)
$pop - Remove First or Last Element
The $pop
operator removes either the first or last element of an array:
// Remove the first element (use -1)
db.arrays.updateOne(
{ _id: 1 },
{ $pop: { scores: -1 } }
)
// Remove the last element (use 1)
db.arrays.updateOne(
{ _id: 1 },
{ $pop: { scores: 1 } }
)
$position - Specify Position for Insertion
Use $position
with $push
and $each
to insert elements at a specific position:
// Add elements at position 2 (0-indexed)
db.students.updateOne(
{ _id: 1 },
{
$push: {
scores: {
$each: [85, 92],
$position: 2
}
}
}
)
$slice - Limit Array Size After Modification
The $slice
modifier limits the array to a specific size after an update operation:
// Keep only the last 5 comments (newest first)
db.posts.updateOne(
{ _id: ObjectId("5f8d2e3f2d7c2a1f4e8b4569") },
{
$push: {
comments: {
$each: [{ text: "Great post!", user: "user123" }],
$slice: -5 // Keep only the last 5 elements
}
}
}
)
Practical Examples
Let's see how these operators work in real-world scenarios:
Example 1: Product Tags Management
Consider an e-commerce application that needs to manage product tags:
// Initial product
db.products.insertOne({
name: "Smart Watch",
price: 199.99,
tags: ["electronics", "wearable"]
})
// Add new tags if they don't exist
db.products.updateOne(
{ name: "Smart Watch" },
{ $addToSet: { tags: { $each: ["bluetooth", "fitness", "wearable"] } } }
)
Result:
{
name: "Smart Watch",
price: 199.99,
tags: ["electronics", "wearable", "bluetooth", "fitness"] // Note "wearable" is not duplicated
}
Example 2: Managing User Activity Feed
For a social media application tracking user activities:
// Add a new activity to the beginning of the feed and keep only latest 10 activities
db.users.updateOne(
{ username: "john_doe" },
{
$push: {
activities: {
$each: [{
type: "post_like",
content: "liked your recent post",
timestamp: new Date()
}],
$position: 0, // Add at the beginning
$slice: 10 // Keep only 10 items
}
}
}
)
Example 3: Comment Moderation System
For a blog with comment moderation features:
// Remove all comments that contain flagged words
db.articles.updateMany(
{},
{
$pull: {
comments: {
text: {
$regex: /inappropriate|offensive/i
}
}
}
}
)
Array Operators in Aggregation Pipeline
MongoDB's aggregation framework also provides powerful array operators:
$unwind - Deconstruct Array Fields
The $unwind
stage deconstructs an array field, creating a separate document for each element:
// Split a document with tag array into multiple documents, one per tag
db.products.aggregate([
{ $match: { name: "Wireless Earbuds" } },
{ $unwind: "$tags" }
])
Input:
{
_id: ObjectId("5f8d2e3f2d7c2a1f4e8b4567"),
name: "Wireless Earbuds",
tags: ["wireless", "bluetooth", "audio"]
}
Output:
{ _id: ObjectId("5f8d2e3f2d7c2a1f4e8b4567"), name: "Wireless Earbuds", tags: "wireless" }
{ _id: ObjectId("5f8d2e3f2d7c2a1f4e8b4567"), name: "Wireless Earbuds", tags: "bluetooth" }
{ _id: ObjectId("5f8d2e3f2d7c2a1f4e8b4567"), name: "Wireless Earbuds", tags: "audio" }
$filter - Select Array Elements
The $filter
operator selects a subset of an array based on specified conditions:
// Get only passing scores (>=70)
db.students.aggregate([
{
$project: {
name: 1,
passingScores: {
$filter: {
input: "$scores",
as: "score",
cond: { $gte: ["$$score", 70] }
}
}
}
}
])
Summary
MongoDB's array operators provide a rich toolkit for working with array data:
- Query Operators (
$all
,$elemMatch
,$size
) help you find documents based on array contents - Update Operators (
$push
,$pull
,$addToSet
,$pop
) modify array fields - Modifiers (
$each
,$position
,$slice
) give you fine-grained control over array operations - Aggregation Operators (
$unwind
,$filter
) transform array data in the aggregation pipeline
Mastering these operators allows you to efficiently store and manipulate complex data structures in MongoDB without requiring multiple queries or extensive client-side processing.
Exercises
- Create a collection of
movies
with fields for title, genres (array), and actors (array). - Write a query to find all movies that are both "Action" and "Comedy" genres.
- Update a movie to add a new actor, but only if that actor isn't already in the cast.
- Remove a specific genre from all movies.
- Write an aggregation pipeline to find the most common actor across all action movies.
Additional Resources
- MongoDB Documentation on Array Query Operators
- MongoDB Documentation on Array Update Operators
- MongoDB Documentation on Aggregation Array Operators
By mastering MongoDB's array operators, you'll be able to work efficiently with complex, nested data structures and build more powerful, flexible applications.
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)