MongoDB $indexOfBytes Operator

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

What You’ll Learn

The $indexOfBytes operator finds where a substring first appears inside a string, measured in bytes. It returns a zero-based byte index or -1 when the text is not found. Use it in aggregation pipelines for URL checks, keyword detection, and text parsing.

01

Substring Search

Find text inside strings.

02

Byte Index

Positions counted in bytes.

03

Syntax

String, search, start, end.

04

$project Stage

Add computed index fields.

05

Use Cases

URLs, keywords, parsing.

06

Not Found

Returns -1 on miss.

Definition and Usage

In MongoDB’s aggregation framework, the $indexOfBytes operator searches a string for the first occurrence of a substring and returns its zero-based byte index. For example, searching "Hello MongoDB" for "Mongo" returns 6 (the byte position where "Mongo" starts). If the substring is absent, the result is -1.

Byte indexing matters because UTF-8 characters can use more than one byte. For plain ASCII text, byte indexes match character positions. When working with emoji or international text, consider $indexOfCP for code-point-based indexing instead.

💡
Beginner Tip

Think of $indexOfBytes as MongoDB’s version of JavaScript’s string.indexOf(substring), but with byte-based offsets. Use it inside aggregation expression stages like $project and $addFields, not as a query filter operator.

📝 Syntax

The $indexOfBytes operator takes a string expression, a substring, and optional byte range bounds:

mongosh
{
  $indexOfBytes: [
    <string expression>,
    <substring expression>,
    <start>,   // optional byte offset, default 0
    <end>      // optional byte offset, default string byte length
  ]
}

Common Patterns

mongosh
// Basic substring search in a field
{ $indexOfBytes: [ "$title", "MongoDB" ] }

// Search from byte offset 5 onward
{ $indexOfBytes: [ "$url", "/", 8 ] }

// Check if substring exists (index >= 0)
{ $gte: [
    { $indexOfBytes: [ "$email", "@" ] },
    0
] }

Syntax Rules

  • First argument — the string to search (field path like "$title" or a literal string).
  • Second argument — the substring to find (literal, field reference, or expression).
  • start — optional byte offset where the search begins (default 0).
  • end — optional byte offset before which the search stops (default string byte length).
  • Returns -1 when the substring is not found in the specified byte range.
  • Indexes are measured in bytes, not Unicode code points.
  • Use inside stages like $project, $addFields, $set, and $cond.

💡 $indexOfBytes vs $indexOfCP

Choose the right string index operator for your data:

ASCII / English text$indexOfBytes and $indexOfCP usually return the same index
Emoji / multi-byte UTF-8 → prefer $indexOfCP for character-based positions
Binary / byte-level work → use $indexOfBytes when byte offsets matter

⚡ Quick Reference

QuestionAnswer
Operator typeAggregation expression operator (string)
Syntax{ $indexOfBytes: [ string, substring, start?, end? ] }
FoundZero-based byte index (0, 1, 2, …)
Not found-1
Common stages$project, $addFields, $cond
Basic
{
  $indexOfBytes: [
    "$title",
    "MongoDB"
  ]
}

Byte index of substring

Not found
{
  $indexOfBytes: [
    "hello",
    "xyz"
  ]
}

Returns -1

With start
{
  $indexOfBytes: [
    "$url",
    "/",
    8
  ]
}

Search from byte 8

Exists check
{
  $gte: [
    { $indexOfBytes: [
      "$email", "@"
    ]},
    0
  ]
}

true if @ found

Examples Gallery

Walk through sample document data, find substring positions with $project, and combine $indexOfBytes with other operators for practical text checks.

📚 Find a Substring Position

Start with a pages collection and locate where a keyword appears in each document’s title field.

Sample Input Documents

Suppose you have a pages collection with title and url fields:

mongosh
[
  { "_id": ObjectId("609c26812e9274a86871bc6a"), "title": "Learn MongoDB Basics", "url": "https://codetofun.com/mongodb" },
  { "_id": ObjectId("609c26812e9274a86871bc6b"), "title": "JavaScript Arrays Guide", "url": "https://codetofun.com/js/arrays" },
  { "_id": ObjectId("609c26812e9274a86871bc6c"), "title": "CSS Flexbox Tutorial", "url": "https://codetofun.com/css/flexbox" }
]

Example 1 — Basic $indexOfBytes on a Field

Find the byte index of "MongoDB" in each page title:

mongosh
db.pages.aggregate([
  {
    $project: {
      title: 1,
      mongoIndex: {
        $indexOfBytes: [ "$title", "MongoDB" ]
      }
    }
  }
])

How It Works

  • In "Learn MongoDB Basics", "MongoDB" starts at byte index 6 (after "Learn ").
  • When the substring is missing, MongoDB returns -1 instead of throwing an error.
  • For ASCII text, byte indexes match what you would expect from character positions.

📈 Practical Patterns

Combine $indexOfBytes with byte offsets, existence checks, and conditional logic.

Example 2 — Search with a Start Byte Offset

Find the first "/" in a URL after the protocol (starting at byte offset 8):

mongosh
db.pages.aggregate([
  {
    $project: {
      url: 1,
      pathSlashIndex: {
        $indexOfBytes: [
          "$url",
          "/",
          8
        ]
      }
    }
  }
])

How It Works

The third argument (start) is a byte offset, not a character index. For https:// URLs, starting at byte 8 skips the protocol and searches only the host and path portion.

Example 3 — Check Whether a Substring Exists

Convert the byte index into a boolean mentionsMongoDB field:

mongosh
db.pages.aggregate([
  {
    $project: {
      title: 1,
      mentionsMongoDB: {
        $gte: [
          { $indexOfBytes: [ "$title", "MongoDB" ] },
          0
        ]
      }
    }
  }
])

How It Works

When the index is -1, $gte returns false. When the substring is found (index 0 or higher), the result is true. This is a common pattern for keyword detection in aggregation pipelines.

Example 4 — $indexOfBytes Inside $cond

Label pages as internal or external based on whether the URL contains your domain:

mongosh
db.pages.aggregate([
  {
    $project: {
      title: 1,
      url: 1,
      linkType: {
        $cond: [
          {
            $gte: [
              { $indexOfBytes: [ "$url", "codetofun.com" ] },
              0
            ]
          },
          "internal",
          "external"
        ]
      }
    }
  }
])

How It Works

If $indexOfBytes finds "codetofun.com" in the URL, the index is >= 0 and $cond outputs "internal". Otherwise the link is labeled "external". Pair with $substrBytes when you need to extract text after the found position.

Bonus — Validate Email Format

A simple check that an email string contains @:

mongosh
db.users.aggregate([
  {
    $project: {
      email: 1,
      hasAtSymbol: {
        $gte: [
          { $indexOfBytes: [ "$email", "@" ] },
          1
        ]
      }
    }
  }
])

How It Works

Requiring index >= 1 ensures @ is not the first character. This is a basic sanity check — not full email validation — but it shows how byte indexes power simple text rules in pipelines.

🚀 Use Cases

  • Keyword detection — check whether titles, descriptions, or logs contain specific text.
  • URL and path parsing — locate slashes, domains, or file extensions in URL strings.
  • Data validation — verify that required symbols (like @ in emails) appear at expected positions.
  • Conditional labeling — drive $cond logic based on whether a substring is present.

🧠 How $indexOfBytes Works

1

MongoDB reads the string and substring

The pipeline evaluates the source string (e.g. "$title") and the text to find (e.g. "MongoDB").

Input
2

$indexOfBytes scans the byte range

MongoDB walks from start to end byte offsets, comparing substrings until a match is found.

Search
3

The byte index is stored in the pipeline

A zero-based byte index is written to your output field, or -1 if no match exists in the range.

Output
=

Precise substring positions

You get byte index data ready for existence checks, conditional labels, and string slicing with $substrBytes.

Conclusion

The $indexOfBytes operator is an essential string tool in MongoDB aggregation pipelines. It tells you where a substring first appears, measured in bytes — enabling keyword checks, URL parsing, and conditional text logic without leaving the database.

For beginners, the key idea is simple: wrap your string and substring in { $indexOfBytes: [ ... ] } inside a stage like $project. A result of -1 means “not found”; any index 0 or higher means the substring was located. For international text or emoji, consider $indexOfCP next.

💡 Best Practices

✅ Do

  • Check for -1 before using the index with $substrBytes
  • Use $gte: [ { $indexOfBytes: ... }, 0 ] for existence booleans
  • Pass start to skip known prefixes (e.g. https://)
  • Use $indexOfBytes for ASCII and byte-level string work
  • Pair with $cond for link type or category labeling

❌ Don’t

  • Use $indexOfBytes as a query filter outside expressions
  • Confuse it with $indexOfArray (arrays vs strings)
  • Assume byte indexes equal character indexes for all UTF-8 text
  • Forget that missing substrings return -1, not null
  • Rely on it alone for full email or URL validation

Key Takeaways

Knowledge Unlocked

Five things to remember about $indexOfBytes

Use these points when searching substrings in MongoDB.

5
Core concepts
📝 02

Byte Index

Positions in UTF-8 bytes.

Syntax
🛠 03

Pipeline Stages

$project, $addFields, $cond.

Usage
🔗 04

URL Parsing

Great for path checks.

Use case
05

Not Found

Returns -1.

Edge case

❓ Frequently Asked Questions

$indexOfBytes returns the zero-based byte index of the first occurrence of a substring inside a string. It is an aggregation expression operator used inside stages like $project and $addFields.
The syntax is { $indexOfBytes: [ <string>, <substring>, <start>, <end> ] }. The start and end arguments are optional byte offsets that limit the search range.
It returns -1 when the substring is not present in the string (within the optional start/end byte range). This matches common indexOf-style behavior.
$indexOfBytes counts positions in bytes (UTF-8 encoding). $indexOfCP counts Unicode code points (characters). For ASCII-only text they behave the same; for emoji or multi-byte characters the indexes can differ.
Yes. start is the byte offset where the search begins (default 0). end is the byte offset before which searching stops (default string byte length). Both are measured in bytes, not characters.

Continue the Operator Series

Move on to $indexOfCP for Unicode code-point indexing, or review $indexOfArray for array searches.

Next: $indexOfCP →

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