MongoDB $in Operator

Beginner
⏱️ 8 min read
📚 Updated: Jul 2026
🎯 4 Examples
Query Filter

What You’ll Learn

The $in operator matches documents when a field equals any value in a list. Use it in $match to filter by multiple categories, statuses, or IDs in one clean query instead of writing many $or conditions.

01

Membership Test

Match any listed value.

02

Two Syntax Forms

Query filter vs expression.

03

$match Stage

Filter by multiple values.

04

Array Fields

Works on array elements too.

05

Use Cases

Categories, roles, IDs.

06

$nin Opposite

Exclude listed values.

Definition and Usage

In MongoDB, the $in operator selects documents where a field’s value appears in a specified array. For example, { status: { $in: [ "active", "pending" ] } } returns every document whose status is either "active" or "pending". It is one of the most common query operators for multi-value filtering.

In aggregation expressions, { $in: [ "$role", [ "admin", "editor" ] ] } returns true or false depending on whether the field value is in the array. This is useful for adding flags or driving $cond logic.

💡
Beginner Tip

Think of $in like JavaScript’s array.includes(value), but in reverse for the query form: MongoDB checks whether the field value is included in your list. It is much cleaner than chaining multiple $eq checks with $or.

📝 Syntax

$in has two forms depending on where you use it:

Query form (in $match or find filters)

mongosh
{ field: { $in: [ <value1>, <value2>, ... ] } }

Aggregation expression form (in $project, $cond, etc.)

mongosh
{ $in: [ <expression>, <array expression> ] }

Syntax Rules

  • Query form — keeps documents where the field equals at least one value in the array.
  • Expression form — returns true when the first operand is found in the second array.
  • If the field is an array, a match occurs when any element in the field array equals a listed value.
  • Values must match BSON types exactly (no automatic type conversion).
  • An empty $in array { field: { $in: [] } } matches no documents.
  • Use $nin for the opposite — exclude documents matching any listed value.

💡 Query Form vs Expression Form

Know which form to use based on your pipeline stage:

$match{ category: { $in: ["books", "games"] } } (filters documents)
$project{ $in: ["$role", ["admin", "editor"]] } (returns boolean)
find()db.products.find({ status: { $in: ["active", "pending"] } }) (works outside aggregation too)

⚡ Quick Reference

QuestionAnswer
Operator typeQuery operator + aggregation expression
Query syntax{ field: { $in: [ val1, val2 ] } }
Expression syntax{ $in: [ expr, array ] }
Expression outputtrue or false
Common stages$match, $project, $cond
$match filter
{
  status: {
    $in: ["active", "pending"]
  }
}

Multiple status values

Expression
{
  $in: [
    "$role",
    ["admin", "editor"]
  ]
}

Returns true/false

Array field
{
  tags: { $in: ["js"] }
}

Matches if tags contains "js"

Empty array
{
  field: { $in: [] }
}

Matches nothing

Examples Gallery

Walk through sample product data, filter by multiple categories with $match, and test membership with the expression form.

📚 Filter by Multiple Values

Use a products collection and find items in selected categories with a single $in condition.

Sample Input Documents

Suppose you have a products collection with name, category, and status fields:

mongosh
[
  { "_id": ObjectId("609c26812e9274a86871bc6a"), "name": "MongoDB Guide", "category": "books", "status": "active" },
  { "_id": ObjectId("609c26812e9274a86871bc6b"), "name": "Chess Set", "category": "games", "status": "active" },
  { "_id": ObjectId("609c26812e9274a86871bc6c"), "name": "Coffee Mug", "category": "kitchen", "status": "archived" }
]

Example 1 — $in in a $match Stage

Find active products in the books or games categories:

mongosh
db.products.aggregate([
  {
    $match: {
      category: { $in: ["books", "games"] },
      status: "active"
    }
  }
])

How It Works

  • category: { $in: ["books", "games"] } matches both the guide and the chess set.
  • The coffee mug is in kitchen, so it is excluded even though it exists in the collection.
  • Combining $in with status: "active" applies both filters (implicit $and).

📈 Practical Patterns

Use $in on array fields, with ObjectIds, and inside conditional expressions.

Example 2 — Match When an Array Field Contains a Value

When a field stores an array (like tags), $in matches if any element is in your list:

mongosh
db.articles.find({
  tags: { $in: ["mongodb", "database"] }
})

How It Works

MongoDB checks each element in the field array against your $in list. A single matching tag is enough for the document to pass the filter.

Example 3 — Add a Boolean Field with $project

Use the expression form to flag users with privileged roles:

mongosh
db.users.aggregate([
  {
    $project: {
      name: 1,
      role: 1,
      isPrivileged: {
        $in: [ "$role", ["admin", "editor", "moderator"] ]
      }
    }
  }
])

How It Works

Unlike the query form, the expression form does not filter documents. It evaluates every document and adds a true or false field based on membership.

Example 4 — $in Inside $cond

Assign a shipping tier based on whether the country is in a domestic list:

mongosh
db.orders.aggregate([
  {
    $project: {
      orderId: 1,
      country: 1,
      shippingTier: {
        $cond: [
          { $in: [ "$country", ["US", "CA", "MX"] ] },
          "domestic",
          "international"
        ]
      }
    }
  }
])

How It Works

When $in returns true, $cond outputs "domestic". Otherwise the order is labeled "international". This pattern is common for routing, pricing, and regional rules.

Bonus — Filter by Multiple ObjectIds

$in is especially handy when fetching documents by a list of IDs:

mongosh
const ids = [
  ObjectId("609c26812e9274a86871bc6a"),
  ObjectId("609c26812e9274a86871bc6c")
];

db.products.find({
  _id: { $in: ids }
})

How It Works

Pass an array of ObjectId values to retrieve multiple documents in one query instead of running separate lookups for each ID.

🚀 Use Cases

  • Multi-value filtering — select documents by category, status, role, or region in one condition.
  • Batch ID lookups — fetch many documents by _id or foreign key using an array of ObjectIds.
  • Tag and skill matching — find articles, jobs, or users when an array field contains any target value.
  • Conditional labeling — use the expression form inside $cond for routing, pricing tiers, or access control flags.

🧠 How $in Works

1

MongoDB reads the field and list

In $match, it checks a field against an array of allowed values. In expressions, it evaluates a value like "$role" against an array like ["admin", "editor"].

Input
2

$in tests membership

MongoDB checks whether the field value (or any array element) equals at least one value in the list. Type and value must match exactly.

Compare
3

Result is applied in the pipeline

In $match, matching documents pass through. In expressions, true or false is stored in the output field.

Output
=

Efficient multi-value matches

You get filtered documents or boolean flags without writing long $or chains.

Conclusion

The $in operator is one of the most practical tools for multi-value filtering in MongoDB. It replaces verbose $or / $eq combinations with a single readable condition, and its expression form powers membership checks inside $project and $cond.

For beginners, remember two forms: query form { field: { $in: [ ... ] } } filters documents, and expression form { $in: [ expr, array ] } returns true or false. Pair it with indexes on filtered fields for the best performance on large collections.

💡 Best Practices

✅ Do

  • Use $in instead of long $or chains for the same field
  • Index fields you frequently filter with $in
  • Use expression form in $project and $cond for membership flags
  • Keep value types consistent (strings vs numbers vs ObjectIds)
  • Use $nin when you need to exclude a list of values

❌ Don’t

  • Pass an empty array to $in expecting all documents (it matches none)
  • Assume type coercion — "10" and 10 are different
  • Use expression form inside $match (it won’t filter as expected)
  • Confuse query $in with aggregation $indexOfArray
  • Put huge unbounded arrays in $in without considering query plan cost

Key Takeaways

Knowledge Unlocked

Five things to remember about $in

Use these points when filtering by multiple values in MongoDB.

5
Core concepts
📝 02

Two Forms

Query filter vs expression.

Syntax
🛠 03

$match Filter

Multi-value matching.

Usage
📦 04

Array Fields

Any element can match.

Pattern
05

Empty Array

{ $in: [] } matches none.

Edge case

❓ Frequently Asked Questions

$in matches documents where a field equals at least one value in a given array. In query filters it keeps matching documents. In aggregation expressions it returns true when the first value appears in the second array.
Query form: { field: { $in: [ value1, value2, ... ] } }. Aggregation expression form: { $in: [ <expression>, <array expression> ] }. The query form filters documents; the expression form returns true or false.
$in is shorter and easier to read when checking one field against several values. { status: { $in: ["active", "pending"] } } is equivalent to { $or: [ { status: "active" }, { status: "pending" } ] } but more concise.
Yes. If the field holds an array, $in matches when at least one element in that field array equals a value in the $in list. For example, tags: ["js", "node"] matches { tags: { $in: ["js"] } }.
$in keeps documents where the field matches any listed value. $nin does the opposite — it excludes documents whose field matches any value in the array.

Continue the Operator Series

Move on to $indexOfArray to locate values inside arrays, or review $eq for single-value equality.

Next: $indexOfArray →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

5 people found this page helpful