Skip to main content

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:

  1. Query Operators - Used to search and filter documents based on array contents
  2. 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.

js
// 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.

js
// Find all students with at least one score between 80 and 90
db.students.find({
scores: {
$elemMatch: { $gte: 80, $lte: 90 }
}
})

Input Document:

js
{
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.

js
// Find all users who have exactly 3 devices
db.users.find({ devices: { $size: 3 } })

Input Documents:

js
{ 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.

js
// Add a new tag to a product
db.products.updateOne(
{ _id: ObjectId("5f8d2e3f2d7c2a1f4e8b4567") },
{ $push: { tags: "waterproof" } }
)

Before:

js
{
_id: ObjectId("5f8d2e3f2d7c2a1f4e8b4567"),
name: "Wireless Earbuds",
tags: ["wireless", "bluetooth", "audio"]
}

After:

js
{
_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.

js
// 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 pushandpush and each

To add multiple elements at once, combine $push with the $each modifier:

js
// 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.

js
// Remove "discontinued" tag from all products
db.products.updateMany(
{},
{ $pull: { tags: "discontinued" } }
)

To remove elements that match multiple criteria, use query conditions:

js
// 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:

js
// 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:

js
// 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:

js
// 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:

js
// 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:

js
{
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:

js
// 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:

js
// 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:

js
// Split a document with tag array into multiple documents, one per tag
db.products.aggregate([
{ $match: { name: "Wireless Earbuds" } },
{ $unwind: "$tags" }
])

Input:

js
{
_id: ObjectId("5f8d2e3f2d7c2a1f4e8b4567"),
name: "Wireless Earbuds",
tags: ["wireless", "bluetooth", "audio"]
}

Output:

js
{ _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:

js
// 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

  1. Create a collection of movies with fields for title, genres (array), and actors (array).
  2. Write a query to find all movies that are both "Action" and "Comedy" genres.
  3. Update a movie to add a new actor, but only if that actor isn't already in the cast.
  4. Remove a specific genre from all movies.
  5. Write an aggregation pipeline to find the most common actor across all action movies.

Additional Resources

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! :)