MongoDB $in Operator

Beginner
5 min read
Updated: Oct 2026
3 examples
Live preview

What Is $in?

$in asks: is this value inside that array? In aggregation it returns a boolean. In queries / $match it keeps documents whose field equals any listed value.

Remember
$in = membership test

Aggregation (boolean):
{ $in: [ <value>, <array> ] }   // value FIRST

Query / $match (filter):
{ field: { $in: [ v1, v2, ... ] } }

found → true / keep doc
not found → false / drop doc
2nd arg must be an array
UsePrefer
Value is in a list / array$in
Value is not in a list$nin
Exact single equality$eq

How to Use $in in MongoDB

Pick the mode that matches your goal: compute a boolean, or filter documents.

  1. Decide the value to look for and the array to search.
  2. For a boolean flag, use { $in: [ value, "$arrayField" ] } in $addFields or $project.
  3. To filter rows by several allowed values, use { field: { $in: [ ... ] } } in $match.
  4. If the array field can be missing, wrap it with $ifNull → [] so aggregation $in does not error.
PieceRequired?Role
ValueYesWhat you are looking for
ArrayYesWhere you look (must resolve to an array)
Stage / queryYes$addFields for flags; $match to filter

Pseudocode

Pseudocode
for each document:
    value = evaluate(left)
    arr = evaluate(right)      // must be an array
    result = false
    for each element in arr:
        if element equals value:
            result = true
            break
    // aggregation: emit boolean
    // $match query form: keep doc if field equals any listed value

Cheat Sheet

Keep these facts handy while testing membership.

TopicDetail
TypeMembership operator (query + aggregation expression)
Aggregation{ $in: [ "bananas", "$in_stock" ] }
Query / $match{ status: { $in: ["A", "B"] } }
Argument orderAggregation: value, then array
ErrorsNot exactly 2 args, or 2nd not an array
RegexNot supported in aggregation $in
vs $ninIn list vs not in list

Live Preview

Array: ["apples", "bananas", "oranges"]. Pick a value and watch aggregation $in return true or false.

Simulates { $in: [ value, ["apples", "bananas", "oranges"] ] }.

Result
value = "bananas"
array = ["apples", "bananas", "oranges"]
$in → true

{ hasFruit: true }

Worked Walkthrough — Has Bananas?

Look for the string "bananas" inside each store’s in_stock array.

Calculation
Rule:
  $in("bananas", in_stock)

["apples", "bananas", "oranges"]
  bananas found → true

["bananas", "pears"]
  bananas found → true

["apples", "oranges"]
  bananas missing → false

Order in the array does not matter — only presence.

MongoDB Examples

We use a small fruit collection of store inventories. First we compute a boolean flag, then we filter stores that stock bananas. Insert the sample data once in mongosh.

Example 1 — Sample Data

Imagine three stores. Each has a location and an in_stock list of fruit. We save them in a collection named fruit.

mongosh
db.fruit.insertMany([
  { _id: 1, location: "24th Street", in_stock: ["apples", "bananas", "oranges"] },
  { _id: 2, location: "36th Street", in_stock: ["bananas", "pears"] },
  { _id: 3, location: "82nd Street", in_stock: ["apples", "oranges"] }
]);

How the Data Is Stored in MongoDB

After the insert, MongoDB keeps three documents in fruit. Run find() to see them:

mongosh
db.fruit.find()

Read those documents like this:

Field in MongoDBExamplePlain English
_id1Store id for this lesson
location"24th Street"Store location label
in_stock["apples", "bananas", ...]Array of fruit names currently stocked
Picture
Look for "bananas" in each list:

  24th: apples, bananas, oranges  → yes
  36th: bananas, pears            → yes
  82nd: apples, oranges           → no

$in asks only "present?" — not "where?" or "how many?"

How It Works

  1. Insert once. insertMany adds three store documents.
  2. MongoDB stores arrays as written. Each in_stock value is a list of strings.
  3. find() shows the same shape. What you inserted is what you get back—ready for $in next.

Example 2 — Boolean Flag with Aggregation $in

Goal: add hasBananas: true/false without removing stores. Remember: value first, array second.

mongosh
db.fruit.aggregate([
  {
    $addFields: {
      hasBananas: {
        $in: ["bananas", "$in_stock"]
      }
    }
  }
]);

How It Works

  1. Read the array. "$in_stock" is the list for each store.
  2. Search for bananas. $in: ["bananas", "$in_stock"] returns true when that string is present.
  3. 82nd Street fails. Its list has apples and oranges only.
  4. Keep all rows. $addFields only adds the boolean flag.

Example 3 — Filter with $match

Same idea, but keep only stores that stock bananas. Wrap the aggregation expression in $expr.

mongosh
db.fruit.aggregate([
  {
    $match: {
      $expr: {
        $in: ["bananas", "$in_stock"]
      }
    }
  }
]);

How It Works

  1. Same stored documents. Still using the three stores from Example 1.
  2. Same membership test. Only rows where bananas appear survive.
  3. $expr unlocks the expression. Aggregation $in inside $match needs $expr.
  4. Query-style tip. For a scalar field against a list of literals, prefer { status: { $in: ["A", "B"] } }—often index-friendly.

Edge Cases & Pitfalls

Check these before shipping $in logic.

order

Value first, array second

Aggregation syntax is [ value, array ]. Swapping them is a common mistake and usually errors or gives wrong results.

array

Second arg must be an array

Missing or null array fields make aggregation $in fail. Use { $ifNull: ["$tags", []] }.

regex

No regex in aggregation $in

Query $in can use regex patterns; aggregation $in does exact equality only.

nested

Nested arrays need exact match

$in: [ ["a"], [ "a" ] ] is false; $in: [ ["a"], [ ["a"] ] ] is true. Types and nesting must match.

Performance Notes

ApproachCostBest for
Query { field: { $in: [...] } }Can use indexesFiltering on stored scalar fields
Aggregation $inPer-document array scanFlags / presence checks on arrays
$match + $expr + $inExpression eval per docFiltering with expression operators

Prefer the query-form $in when you filter on an indexed field. Keep candidate lists reasonably small. Filter early with $match when possible.

Key Takeaways

  • Role: is this value in that array?
  • Aggregation: [ value, array ] → boolean.
  • Query: { field: { $in: [...] } } filters documents.
  • Opposite: use $nin when the value must not appear.

One line: $in answers “is this value among these options?”—as a boolean in aggregation, or as a multi-value filter in $match.

Frequently Asked Questions

In aggregation, $in returns true when a value appears in an array. In queries and $match, { field: { $in: [ ... ] } } keeps documents where the field equals any listed value.
Aggregation: { $in: [ <value>, <array> ] } — value first, array second. Query / $match: { field: { $in: [ value1, value2, ... ] } }.
Aggregation $in returns a boolean and needs exactly [value, array]. Query $in filters documents. Aggregation $in does not match with regular expressions.
Aggregation $in errors if the second expression does not resolve to an array. Guard missing fields with $ifNull: [ "$tags", [] ].
$in is true when the value is found. $nin is true when the value is not found (or, in query form, excludes matching documents).
Yes for query $in: the document matches if any element of the field array equals any listed value. Aggregation $in checks whether one value appears inside one array expression.

Next: $indexOfArray

Return the first index of a value inside an array (or -1 if missing).

$indexOfArray tutorial →

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.

9 people found this page helpful