MongoDB Logical Operators
In MongoDB, logical operators allow you to create complex query conditions by combining multiple expressions. These operators help you filter documents based on multiple criteria, giving you precise control over which documents are returned in your query results.
Introduction
When querying a MongoDB database, you'll often need to filter data based on multiple conditions. For example, you might want to find all products that are either in stock AND on sale, or products that are neither in stock NOR on sale. This is where logical operators become essential.
MongoDB provides four main logical operators:
$and
: Returns documents that match all specified conditions$or
: Returns documents that match at least one of the specified conditions$not
: Returns documents that do not match the specified condition$nor
: Returns documents that fail to match all specified conditions
Let's explore each of these operators in detail with practical examples.
The $and
Operator
The $and
operator performs a logical AND operation on an array of expressions and returns documents that satisfy all the expressions.
Syntax
{ $and: [ { <expression1> }, { <expression2> }, ... ] }
Basic Example
Let's say we have a collection of products and want to find all products that are both in stock and priced under $100:
db.products.find({
$and: [
{ inStock: true },
{ price: { $lt: 100 } }
]
})
This query returns documents where both conditions are true: inStock
is true
and price
is less than 100.
Implicit AND Operations
MongoDB actually performs an implicit AND operation when you provide multiple key-value pairs in a query document. So the previous query could be simplified to:
db.products.find({
inStock: true,
price: { $lt: 100 }
})
Both queries return the same results. However, the explicit $and
operator becomes necessary when you need to include the same field or operator more than once in a query.
When to Use Explicit $and
For example, if you want to find products with prices between 100, but also excluding exactly $50:
db.products.find({
$and: [
{ price: { $gt: 10 } },
{ price: { $lt: 100 } },
{ price: { $ne: 50 } }
]
})
In this case, you can't use implicit AND because you're specifying multiple conditions for the same price
field.
The $or
Operator
The $or
operator performs a logical OR operation on an array of expressions and returns documents that satisfy at least one of the expressions.
Syntax
{ $or: [ { <expression1> }, { <expression2> }, ... ] }
Basic Example
Let's find all products that are either on sale OR have a high customer rating:
db.products.find({
$or: [
{ onSale: true },
{ customerRating: { $gte: 4.5 } }
]
})
This query returns documents where either onSale
is true
OR customerRating
is greater than or equal to 4.5 (or both).
Practical Example
Finding products that meet specific customer search criteria:
db.products.find({
$or: [
{ category: "electronics" },
{ tags: "technology" },
{ name: { $regex: "phone", $options: "i" } }
]
})
This query finds products that are either in the "electronics" category, have a "technology" tag, or have "phone" in their name (case insensitive).
The $not
Operator
The $not
operator performs a logical NOT operation on the specified expression and returns documents that do not match the expression.
Syntax
{ field: { $not: { <operator-expression> } } }
Basic Example
Find all products that are not priced above $100:
db.products.find({
price: { $not: { $gt: 100 } }
})
This query returns documents where the price
is not greater than 100 (which means it's either less than or equal to 100, or the price field doesn't exist).
Practical Example
Find documents that don't match a regular expression:
db.products.find({
description: { $not: { $regex: "limited edition", $options: "i" } }
})
This returns products whose descriptions do not contain the phrase "limited edition".
The $nor
Operator
The $nor
operator performs a logical NOR operation on an array of expressions and returns documents that fail to match all of the expressions.
Syntax
{ $nor: [ { <expression1> }, { <expression2> }, ... ] }
Basic Example
Find products that are neither out of stock nor on sale:
db.products.find({
$nor: [
{ inStock: false },
{ onSale: true }
]
})
This query returns documents where both expressions are false (meaning inStock
is not false
and onSale
is not true
).
Practical Example
Filtering out multiple unwanted categories:
db.products.find({
$nor: [
{ category: "clothing" },
{ category: "accessories" },
{ price: { $lt: 20 } }
]
})
This query returns products that are not in the "clothing" or "accessories" categories and don't have a price less than 20.
Combining Logical Operators
You can nest logical operators to create more complex queries.
Example: Combining $and
and $or
Find products that are either:
- In the "electronics" category AND priced under $500, OR
- In the "books" category AND have a rating of at least 4 stars
db.products.find({
$or: [
{
$and: [
{ category: "electronics" },
{ price: { $lt: 500 } }
]
},
{
$and: [
{ category: "books" },
{ rating: { $gte: 4 } }
]
}
]
})
Real-World Application: E-commerce Filtering
Let's look at a practical example for an e-commerce website where users can filter products with multiple criteria:
db.products.find({
$and: [
{ category: "smartphones" },
{
$or: [
{ brand: "Apple" },
{ brand: "Samsung" }
]
},
{
$and: [
{ price: { $gte: 500 } },
{ price: { $lte: 1000 } }
]
},
{
$or: [
{ features: "waterproof" },
{ features: "5G" }
]
},
{
$nor: [
{ status: "discontinued" },
{ inStock: false }
]
}
]
})
This query finds:
- Smartphones
- Made by Apple or Samsung
- Priced between 1000
- That have either "waterproof" or "5G" features
- That are not discontinued and are in stock
Real-World Application: User Search
For a user management system where you need to find specific users matching complex criteria:
db.users.find({
$and: [
{ "account.status": "active" },
{
$or: [
{ role: "admin" },
{
$and: [
{ role: "editor" },
{ "permissions.canPublish": true }
]
}
]
},
{
$nor: [
{ lastLogin: { $lt: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000) } }, // Not logged in for 30 days
{ "security.mfaEnabled": false } // No MFA enabled
]
}
]
})
This query finds:
- Active users
- Who are either admins OR editors with publishing permissions
- Who have logged in within the last 30 days AND have MFA enabled
Performance Considerations
When using logical operators, keep these performance tips in mind:
- Use indexes for fields involved in your queries whenever possible
- Place the most selective conditions first in
$and
operations - For
$or
queries, each condition should be indexable for best performance - Complex queries with many logical operators may benefit from the aggregation pipeline for better performance
Summary
MongoDB's logical operators provide powerful tools for creating complex queries:
- Use
$and
when all conditions must be met - Use
$or
when at least one condition must be met - Use
$not
to negate a specific condition - Use
$nor
when none of the conditions should be met
By combining these operators, you can create highly specific queries that precisely target the documents you need. This ability to filter data with complex conditions is essential for building flexible and powerful applications with MongoDB.
Practice Exercises
-
Write a query that finds all products in the "electronics" category with a price between 500 and that have at least a 4-star rating.
-
Create a query that finds users who are either premium members OR have made at least 5 purchases, AND have been customers for more than a year.
-
Find all orders that were neither placed on a weekend NOR have a status of "cancelled", AND have a total amount greater than $50.
Additional Resources
- MongoDB Official Documentation on Logical Query Operators
- MongoDB Query Optimization
- MongoDB Aggregation Pipeline - for more complex data processing
Remember that mastering logical operators is key to writing effective MongoDB queries that can handle real-world data filtering requirements.
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)