$strcasecmp is a MongoDB aggregation expression that compares two strings without regard to letter case. It returns 0 (equal), -1 (first is less), or 1 (first is greater). Behavior is well-defined for ASCII.
Remember
$strcasecmp = case-insensitive string compare for aggregation
{ $strcasecmp: [ <string1>, <string2> ] }
"Active" vs "active" → 0 (equal, ignore case)
"apple" vs "Banana" → -1 (a < b)
"Zoo" vs "apple" → 1 (z > a)
equal check → $eq([ $strcasecmp(...), 0 ])
case-sensitive → use $eq / $cmp instead
Read -1, 0, or 1 as less / equal / greater (case ignored).
For a boolean match, wrap with $eq: compare the result to 0.
Piece
Required?
Role
String 1
Yes
Left side of the comparison
String 2
Yes
Right side (field or literal)
$eq … 0
No
Turn the result into a true/false match
Pseudocode
Pseudocode
for each document:
a = evaluate(string1)
b = evaluate(string2)
// case-insensitive ASCII compare
if lower(a) < lower(b):
result = -1
else if lower(a) > lower(b):
result = 1
else:
result = 0
emit { ..., field: result }
Reference
Cheat Sheet
Keep these facts handy while writing case-insensitive comparisons.
We store two users with mixed-case roles. First we compare each role to "admin", then we build a boolean isAdmin flag. Run these in mongosh after inserting the sample data once.
Example 1 — Sample Data
Imagine two users: Alice with role Admin, and Bob with role editor. We save them in a collection named users.
Same stored users. Still using Alice and Bob from Example 1.
Compare ignoring case.$strcasecmp still returns 0 or 1.
Turn into a boolean.$eq checks whether that result is exactly 0.
Easy check. Alice → true; Bob → false.
Edge Cases & Pitfalls
Check these before using $strcasecmp in production pipelines.
not boolean
Result is -1 / 0 / 1
Do not treat the raw result as true/false. For a match flag, compare to 0 with $eq.
ASCII
Well-defined for ASCII
Official docs note well-defined behavior for ASCII. For complex Unicode case rules, consider collation or careful normalization.
null
Null compares as null
null equals null (0). A non-null string is greater than null (1). Missing fields behave like null.
vs $eq
$eq alone is case-sensitive
{ $eq: ["Admin", "admin"] } is false. Use $strcasecmp when case should not matter.
Analysis
Performance Notes
Approach
Cost
Best for
$strcasecmp alone
Per-document string compare
Flags, computed fields
$match + $expr + $strcasecmp
Expression filter (not a simple index equality)
Case-insensitive filters
Store a normalized field
Index-friendly equality
Hot case-insensitive lookups
For frequent case-insensitive lookups, a stored lowercase field (or collation) often beats scanning with $expr. Filter early with $match when only some documents need the check.
Remember
Key Takeaways
Role: case-insensitive string compare → -1/0/1.
Equal: result 0 (or $eq with 0 for a boolean).
ASCII: well-defined for ASCII strings.
Case-sensitive: use $eq instead.
One line:$strcasecmp answers “how do these two strings order if we ignore capital letters?”
Frequently Asked Questions
$strcasecmp compares two strings without regard to letter case. It returns 0 when they match, -1 when the first is less than the second, and 1 when the first is greater. Use it inside aggregation expression stages such as $project and $addFields.
Use { $strcasecmp: [ <string1>, <string2> ] }. Both arguments can be field references like "$status" or literal strings like "active".
Compare the result to zero: { $eq: [ { $strcasecmp: [ "$field", "target" ] }, 0 ] }. That returns true when the strings match case-insensitively.
$eq is case-sensitive: "Active" and "active" are not equal. $strcasecmp ignores case, so those two compare as equal (returns 0).
Yes. Wrap it inside $expr, or use it in an aggregation $match stage. Example: { $expr: { $eq: [ { $strcasecmp: [ "$role", "admin" ] }, 0 ] } }.
Official docs say behavior is well-defined for ASCII. For full Unicode case folding, prefer collation-aware queries or normalize with $toLower / $toUpper carefully for your locale.