ตัวดำเนินการตรรกะ: $and, $or, $nor, $not
ผู้เรียนจะรวมเงื่อนไขหลายรายการด้วยตัวดำเนินการตรรกะเพื่อเขียนตรรกะการกรองแบบซับซ้อน
ตัวดำเนินการตรรกะ: $and, $or, $nor, $not เป็นบทเรียน MongoDB Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน MongoDB Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส MongoDB Academy มีบทเรียนทั้งหมด 4 บทเรียน
บางส่วนของบทเรียนนี้ยังไม่ได้รับการแปล และแสดงเป็นภาษาอังกฤษ
Why Logical Operators Are Needed
Most query filters involve conditions on multiple fields, and not all of them should be combined with a simple AND. Sometimes you want documents that meet any of several conditions, or you want to exclude documents matching a pattern. MongoDB's logical operators—$and, $or, $nor, and $not—give you full boolean control over your filter conditions.
Understanding when to use each operator—and knowing the implicit AND shortcut—makes your queries more readable and performant.
Implicit AND: The Default
When you list multiple field conditions in a single filter object, MongoDB applies them as an implicit AND—all conditions must be true for a document to match. This is the default and most common case.
The implicit AND is both more concise and slightly more efficient than the explicit $and operator because MongoDB can optimize field-level conditions independently. Use implicit AND whenever your conditions target different fields with no ambiguity.
// Implicit AND - all three conditions must be true
db.users.find({
age: { $gte: 18 },
active: true,
role: 'user'
});
// Equivalent to: age >= 18 AND active = true AND role = 'user'
// Same with explicit $and (more verbose, same result)
db.users.find({
$and: [
{ age: { $gte: 18 } },
{ active: true },
{ role: 'user' }
]
});When You Need Explicit $and
Explicit $and is required in one specific situation: when you need to apply multiple conditions to the same field using different operators, and you cannot express them in a single object (because JavaScript objects cannot have duplicate keys).
The most common case is combining two $or conditions that both reference the field. However, range conditions on a single field ({ price: { $gte: 20, $lte: 100 } }) work fine in one object—explicit $and is only needed when the expressions cannot be combined into one field value.
// Explicit $and: two $or conditions that cannot be merged
db.products.find({
$and: [
{ $or: [{ category: 'Electronics' }, { category: 'Computers' }] },
{ $or: [{ brand: 'Apple' }, { brand: 'Samsung' }] }
]
});
// (category is Electronics OR Computers)
// AND (brand is Apple OR Samsung)
// If you just wrote { $or: [...], $or: [...] }
// JS would only keep the last $or!$or: At Least One Condition
$or takes an array of filter conditions and matches documents where at least one of the conditions is true. It is the MongoDB equivalent of SQL's OR keyword.
Use $or when you have alternative paths to the same result—for example, finding users who are either admins or have been active in the last 30 days. One important performance note: if each condition is indexed separately, MongoDB can use index union to satisfy the query—but a single compound index covering all conditions is often faster.
// Find users who are admins OR have been recently active
const recentDate = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000);
db.users.find({
$or: [
{ role: 'admin' },
{ lastLoginAt: { $gte: recentDate } }
]
});
// Find products on sale OR low in stock
db.products.find({
$or: [
{ onSale: true },
{ stock: { $lt: 5 } }
]
});$nor: None of the Conditions
$nor matches documents where none of the given conditions is true—it is the complement of $or. A document must fail ALL conditions in the $nor array to be returned.
$nor is less common than $or but useful for exclusion logic: 'find products that are neither discontinued nor out of stock nor in the archived category.' It also matches documents where the queried fields are absent, since absent fields do not match any positive condition.
// Exclude multiple status values
db.orders.find({
$nor: [
{ status: 'cancelled' },
{ status: 'refunded' },
{ status: 'archived' }
]
});
// Matches orders where status is NONE of the above
// (equivalent to status NOT IN [...])
// Could also write as:
db.orders.find({ status: { $nin: ['cancelled', 'refunded', 'archived'] } });$not: Negate a Single Operator
$not inverts the result of a single field-level operator expression. Unlike $nor (which takes an array of full filter conditions), $not wraps a single operator or regex: { price: { $not: { $gt: 100 } } }.
$not also matches documents where the field does not exist. It is often redundant with $ne or $nin, but is specifically useful for negating regular expressions: { name: { $not: /^admin/i } }—there is no $ne equivalent for regex patterns.
// $not with a comparison operator
db.products.find({
price: { $not: { $gt: 100 } }
});
// Matches: price <= 100 AND documents where price field is absent
// $not with a regex - negate a pattern
db.users.find({
username: { $not: /^admin/i }
});
// Users whose username does NOT start with 'admin' (case-insensitive)
// Negating $in
db.items.find({
status: { $not: { $in: ['draft', 'archived'] } }
});Combining $and, $or, and $not
Logical operators can be nested to express arbitrarily complex boolean logic. Think of building a logic tree: outer $and conditions are connected at the top level, and $or sub-expressions express alternatives within a branch.
Complex nested boolean queries can be hard to read—consider breaking them into named JavaScript variables or building the filter object programmatically from user input, rather than nesting them five levels deep in one object literal.
// Complex: (premium OR admin) AND (active) AND NOT (suspended)
db.users.find({
$and: [
{ $or: [{ role: 'premium' }, { role: 'admin' }] },
{ active: true },
{ suspended: { $not: { $eq: true } } }
]
});
// Programmatic filter building (cleaner)
const filter = {};
if (roles.length > 0) filter['$or'] = roles.map(r => ({ role: r }));
if (activeOnly) filter.active = true;
db.users.find(filter);$or Performance Considerations
$or queries have specific index usage behavior. MongoDB evaluates each branch of $or independently and merges results:
- If each branch can use an index, MongoDB performs an index union—efficient
- If any branch cannot use an index, MongoDB falls back to a collection scan for that branch—potentially slow
For best performance, ensure every branch of $or has a matching index. When $or conditions can be rewritten as $in on the same field ({ status: { $in: ['a','b'] } }), do so—$in is more efficient than a two-branch $or on the same field.
// Inefficient: $or that prevents index use
db.products.find({
$or: [
{ price: { $lt: 50 } },
{ description: { $regex: 'sale' } } // Regex on unindexed field = COLLSCAN
]
});
// The regex branch causes a full scan for all matched documents
// Better: use $in when possible (same field, multiple values)
db.products.find({ category: { $in: ['A', 'B', 'C'] } });
// Single index lookup is more efficient than 3-branch $orLogical Operators in the Aggregation Pipeline
In aggregation pipeline stages like $match, the same logical operators work exactly as they do in find(). Place $match with your logical conditions as early as possible in the pipeline to reduce the number of documents processed by subsequent stages.
Inside pipeline expression operators (like $project or $addFields), logical operators have a slightly different syntax: { $and: [expr1, expr2] } as expression operators rather than query operators. The query ($match) and expression ($project) contexts use the same operator names but different syntaxes.
// $match with logical operators in an aggregation pipeline
db.orders.aggregate([
{
$match: {
$or: [
{ status: 'shipped' },
{ status: 'delivered' }
],
createdAt: { $gte: new Date('2024-01-01') }
}
},
{ $group: { _id: '$customerId', totalOrders: { $sum: 1 } } }
]);Practical Filter Builder Pattern
In real applications, query filters are often built dynamically from user input (search forms, API query params). Build the filter object programmatically and only add conditions when the parameter is provided—do not add an $or: [] with empty arrays, which would match nothing.
Validate and sanitize all user-provided values before including them in a query. Never pass raw user strings directly to $regex without escaping—an attacker could inject a catastrophically slow regex pattern (ReDoS attack).
function buildProductFilter(params) {
const filter = {};
if (params.categories && params.categories.length > 0) {
filter.category = { $in: params.categories };
}
if (params.minPrice != null) {
filter.price = { ...filter.price, $gte: params.minPrice };
}
if (params.maxPrice != null) {
filter.price = { ...filter.price, $lte: params.maxPrice };
}
if (params.inStockOnly) {
filter.stock = { $gt: 0 };
}
return filter;
}
const results = await db.collection('products')
.find(buildProductFilter(req.query)).toArray();Short-Circuit Evaluation in MongoDB
MongoDB evaluates logical operator expressions but does NOT necessarily short-circuit like JavaScript. The query planner may reorder conditions for efficiency—for example, moving a condition that uses an index before one that does not, regardless of their order in the query document.
One important implication: in , if the first branch causes a full collection scan, the entire query may scan the collection even if the second branch is efficiently indexed. This is why ensuring every branch of is indexed is so critical for performance. Use explain() to verify the execution plan matches your expectations.
// MongoDB may reorder these conditions for efficiency:
db.products.find({
: [
{ category: 'Electronics' }, // If indexed: fast point lookup
{ description: /wireless/i } // Not indexed: slow scan
]
});
// Even though category (indexed) is listed first,
// if MongoDB cannot use index union, it may scan all docs.
// Always verify with .explain('executionStats')Quick Check
Test your understanding of MongoDB & NoSQL Databases concepts from this lesson.
Lesson Recap
In this lesson you learned: implicit AND is the default when listing multiple fields in one filter object—explicit $and is only needed when you cannot express conditions as unique keys (e.g., two $or blocks), $or matches any one condition and uses index union when each branch is indexed, and $not inverts a single operator and is especially useful for negating regex patterns where $ne does not apply. Next up we explore element operators like $exists and $type for handling optional and mixed-type fields.
เรียนรู้ JavaScript ด้วย AI tutor — ฟรี
เขียนและเรียกใช้โค้ดจริงในเบราว์เซอร์ของคุณ รับความช่วยเหลือทันทีจาก AI tutor 24/7 และเรียนรู้ต่อจากที่คุณหยุดบนเว็บหรือในแอป
- คอร์ส
- 30
- บทเรียน
- 120
คำถามที่พบบ่อย
บทเรียน “ตัวดำเนินการตรรกะ: $and, $or, $nor, $not” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “ตัวดำเนินการตรรกะ: $and, $or, $nor, $not” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส MongoDB Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส MongoDB Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “ตัวดำเนินการตรรกะ: $and, $or, $nor, $not”
ผู้เรียนจะรวมเงื่อนไขหลายรายการด้วยตัวดำเนินการตรรกะเพื่อเขียนตรรกะการกรองแบบซับซ้อน คุณปฏิบัติ MongoDB Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน MongoDB Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน MongoDB Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน
บทเรียน “ตัวดำเนินการตรรกะ: $and, $or, $nor, $not” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน MongoDB Academy นี้ได้ไหม
ได้ บทเรียน MongoDB Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- ตัวดำเนินการเปรียบเทียบ: $eq, $gt, $lt, $in
- ตัวดำเนินการตรรกะ: $and, $or, $nor, $not
- ตัวดำเนินการองค์ประกอบและการตรวจสอบชนิด
- คิวรีนิพจน์ปกติและการจับคู่รูปแบบ