Menu

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.