HOWTO · MongoDB
How to Query With String Length in MongoDB
Find MongoDB documents by string length using $expr and $strLenCP, an aggregation pipeline, $where, or a regular expression, with guidance on Unicode and field types.
On this page
To find MongoDB documents whose string field has exactly five Unicode code points, use $expr with $strLenCP in find(): db.mydata.find({ $expr: { $eq: [{ $strLenCP: "$Name" }, 5] } }). This short form assumes every document has a string-valued Name field. A guarded form below handles mixed field types.
Query documents by string length in MongoDB
Use one collection and consistent field names when comparing approaches. The following standalone JavaScript example defines six sample documents and filters them locally by code-point length. It requires no database connection and does not demonstrate MongoDB server execution.
const documents = [
{ _id: 1, Name: "hello" },
{ _id: 2, Name: "world" },
{ _id: 3, Name: "abcdefgh" },
{ _id: 4, Name: "ijklmnop" },
{ _id: 5, Name: "apple" },
{ _id: 6, Name: "grape" }
];
const matches = documents.filter(document => [...document.Name].length === 5);
console.log(JSON.stringify(matches, null, 2));
[
{
"_id": 1,
"Name": "hello"
},
{
"_id": 2,
"Name": "world"
},
{
"_id": 5,
"Name": "apple"
},
{
"_id": 6,
"Name": "grape"
}
]
For this data, the five-code-point matches are documents 1, 2, 5, and 6: hello, world, apple, and grape. Documents 3 and 4 each have eight code points.
The database commands in this article are unexecuted MongoDB shell illustrations. They require a connected MongoDB server. To create the sample in a new mydata collection, use db.mydata.insertMany([{ _id: 1, Name: "hello" }, { _id: 2, Name: "world" }, { _id: 3, Name: "abcdefgh" }, { _id: 4, Name: "ijklmnop" }, { _id: 5, Name: "apple" }, { _id: 6, Name: "grape" }]). Use a separate sample collection to avoid existing _id conflicts.
Use $where to filter by string length
The $where query operator evaluates server-side JavaScript; its documentation describes deployment restrictions and the requirement that server-side scripting be enabled. Where server-side JavaScript is available, the sample can be filtered with db.mydata.find({ $where: function () { return typeof this.Name === "string" && this.Name.length === 5; } }).
The type check skips missing, null, and non-string values. Change === 5 to > 5 for a greater-than condition. JavaScript’s .length counts UTF-16 code units: an emoji outside the basic multilingual plane occupies two units. Consequently, this approach agrees with the other examples on the ASCII sample but is not a general substitute for code-point counting. Use $expr when you want to express the condition without server-side JavaScript.
Use $expr and $strLenCP in find()
The $expr operator lets find() evaluate aggregation expressions. $strLenCP counts Unicode code points, while $eq compares that count with your target. Replace $eq with $gt for lengths greater than five, or $gte to include five.
As the $strLenCP documentation explains, its input must resolve to a string; null or missing inputs cause an error. Use a conditional expression when Name may have another type:
db.mydata.find({ $expr: { $cond: [{ $eq: [{ $type: "$Name" }, "string"] }, { $eq: [{ $strLenCP: "$Name" }, 5] }, false] } })
Here $cond evaluates the length comparison only for strings and returns false otherwise. An empty string has length zero; a missing or null field is skipped rather than treated as an empty string. A separate condition joined with $and should not be relied on to evaluate first and protect $strLenCP from unsuitable inputs.
Code points differ from UTF-8 bytes and from visible characters: a letter followed by a combining accent consists of two code points. Choose the counting rule your application needs.
The official documentation links in this article are provided for reference; their live availability and current contents have not been checked here.
For nested fields, change the expression reference to a dotted path such as "$parentField.childField", including in the type check. Combine complete conditions with $and or $or when filtering multiple fields.
Filter by string length with an aggregation pipeline
Use an aggregation pipeline when filtering is part of a larger transformation. For the sample collection, this $match stage selects the two eight-code-point strings:
db.mydata.aggregate([{ $match: { $expr: { $eq: [{ $strLenCP: "$Name" }, 8] } } }])
The matching documents are { _id: 3, Name: "abcdefgh" } and { _id: 4, Name: "ijklmnop" }. This illustration assumes string inputs, as in the sample. For mixed data, replace its $expr value with the guarded $cond expression from the preceding section and set the target to eight. Add $project to reshape the matching documents or $group to summarize them.
Match a fixed string length with a regular expression
For the sample’s scalar strings containing ASCII letters, use db.mydata.find({ Name: { $regex: "^.{5}$" } }). The anchors constrain the match, and {5} repeats the dot five times, selecting documents 1, 2, 5, and 6.
The official $regex documentation explains the relevant matching options and anchors. This pattern needs qualification for arbitrary text: dot normally excludes newlines, and $ can match before a final newline. A regex field predicate can also match a string element within an array. Prefer the guarded $strLenCP query when you need a scalar string and an explicit code-point count. Choose regex when character patterns are part of the task, and measure performance on your own workload before making efficiency or indexing decisions.