MongoDB $type Query Operator
MongoDB’s $type query operator selects documents whose field values have a specified BSON type. It is useful when a collection contains inconsistent data—for example, when some price values are numbers and others were stored as strings.
This article covers the query predicate used in find() filters. MongoDB also has an aggregation expression named $type; it has different syntax and array behavior.
Syntax
{ <field>: { $type: <type-or-alias> } }
Use a BSON type number or its string alias. To match any of several types, pass an array:
{ <field>: { $type: [ <type-or-alias>, ... ] } }
For example, this query finds products whose price is stored as either a 32-bit integer or a decimal value:
db.products.find({ price: { $type: ["int", "decimal"] } })
The official MongoDB $type query operator reference documents the accepted aliases and matching behavior.
BSON type aliases
The query operator accepts these BSON type aliases and numeric codes:
| Alias | BSON type | Code | Notes |
|---|---|---|---|
double |
Double | 1 | |
string |
String | 2 | |
object |
Object | 3 | |
array |
Array | 4 | Matches a field whose value is an array. |
binData |
Binary data | 5 | |
undefined |
Undefined | 6 | Deprecated BSON type. |
objectId |
ObjectId | 7 | |
bool |
Boolean | 8 | |
date |
Date | 9 | |
null |
Null | 10 | |
regex |
Regular expression | 11 | |
dbPointer |
DBPointer | 12 | Deprecated BSON type. |
javascript |
JavaScript | 13 | |
symbol |
Symbol | 14 | Deprecated BSON type. |
javascriptWithScope |
JavaScript with scope | 15 | Deprecated BSON type. |
int |
32-bit integer | 16 | |
timestamp |
Timestamp | 17 | |
long |
64-bit integer | 18 | |
decimal |
Decimal128 | 19 | |
minKey |
MinKey | -1 | |
maxKey |
MaxKey | 127 | |
number |
Numeric values | — | Matches double, int, long, or decimal. |
The number alias is convenient when the stored numeric representation may vary. The deprecated BSON types remain in the list for compatibility with older data; avoid using them for new values. See MongoDB’s BSON types reference for the complete type definitions. To convert values instead of filtering by type, see MongoDB type conversion operators.
Examples
Assume users contains documents like these:
db.users.insertMany([
{ _id: 1, name: "Ada", age: 37, tags: ["sql", "database"] },
{ _id: 2, name: "Grace", age: NumberInt(42), tags: ["compiler"] },
{ _id: 3, name: "Linus", age: "42", tags: "operating systems" },
{ _id: 4, name: "Edsger", tags: [] }
])
Find a field with a specific type
Find users whose age is stored as a string:
db.users.find({ age: { $type: "string" } })
This matches Linus’s document. It does not convert the string "42" to a number.
Match any numeric BSON type
Find users whose age is stored as a number, whether it is a double, integer, long, or decimal:
db.users.find({ age: { $type: "number" } })
Using { $type: 1 } would match only the double type, not every numeric type.
Match an array field
For the query predicate, $type can match an element inside an array. This query finds users whose tags value is an array containing a string; it also matches a scalar string value:
db.users.find({ tags: { $type: "string" } })
To find only documents where tags itself is an array, use the array alias:
db.users.find({ tags: { $type: "array" } })
That distinction matters: $type: "string" matches _id: 1, _id: 2, and _id: 3, while $type: "array" matches _id: 1, _id: 2, and _id: 4.
Find existing fields that are not numeric
Combine $exists with $not when the field must be present but must not contain a numeric BSON value:
db.users.find({
age: { $exists: true, $not: { $type: "number" } }
})
Without $exists: true, documents that do not contain age can also satisfy a negated field condition. See MongoDB’s $not query operator and $exists query operator references for their full behavior.
Query $type and aggregation $type are different
In a query filter, $type selects documents. In an aggregation expression, $type returns the type name of an expression:
db.users.aggregate([
{
$project: {
ageType: { $type: "$age" }
}
}
])
The aggregation expression returns values such as "int", "double", or "string". It treats an array as the type "array" instead of inspecting its elements, and returns "missing" when the referenced field is absent. These rules differ from the query predicate’s array matching behavior. See the official aggregation $type expression reference for details.
Use $exists to test whether a field is present in a query. Do not use an aggregation result of "missing" as a query type alias.