Docs Menu

Docs HomeDevelop ApplicationsMongoDB Manual

Wildcard Indexes on Embedded Objects and Arrays

On this page

  • Wildcard Indexes on Embedded Objects
  • Wildcard Indexes on Arrays
  • Learn More

Wildcard indexes have specific behavior when indexing embedded object and array fields:

  • If the field is an object, the wildcard index descends into the object and indexes its contents. The wildcard index continues descending into any additional embedded documents it encounters.

  • If the field is an array, the wildcard index traverses the array and indexes each element:

    • If the element is an object, the wildcard index descends into the object to index its contents.

    • If the element is an array (that is, an array which is embedded directly within the parent array), the wildcard index does not traverse the embedded array, but indexes the entire array as a single value.

  • For all other fields, the index stores the primitive value. A primitive value is a non-object, non-array value.

The wildcard index continues traversing any additional embedded objects or arrays until it reaches a primitive value. It then indexes the primitive value, along with the full path to that field.

When a wildcard index encounters an embedded object, it descends into the object and indexes its contents. For example, consider this document:

db.users.insertOne( {
account: {
username: "SuperAdmin01",
contact: {
phone: "123-456-7890",
email: "xyz@example.com"
},
access: {
group: "admin"
}
}
} )

A wildcard index that includes the account field descends into the account object to traverse and index its contents:

  • For each subfield which is itself an object (for example, account.contact and account.access), the index descends into the object and records its contents.

  • For all other subfields, the index records the primitive value into the index.

Given the sample document, the wildcard index adds the following records to the index:

  • "account.username" : "SuperAdmin01"

  • "account.contact.phone" : "123-456-7890"

  • "account.contact.email" : "xyz@example.com"

  • "account.access.group" : "admin"

When a wildcard index encounters an array, it traverses the array to index its elements. If the array element is itself an array (an embedded array), the index records the entire embedded array as a value instead of traversing its contents.

For example, consider this document:

db.fleet.insertOne( {
"ship": {
"coordinates" : [
[-5, 10],
[-7, 8]
],
"type": "Cargo Ship",
"captains": [
{
"name": "Francis Drake",
"crew": [ "first mate", "carpenter" ]
}
]
}
} )

A wildcard index which includes the ship field descends into the object to traverse and index its contents:

  • For each element which is an array:

    • If the element is itself an array (as in an embedded array), the index records the entire array as a value.

    • If the element is an object, the index descends into the object to traverse and index its contents.

    • If the element is a primitive value, the index records that value.

  • For non-array, non-object fields, the index records the primitive value into the index.

Given the sample document, the wildcard index adds the following records to the index:

  • "ship.coordinates" : [-5, 10]

  • "ship.coordinates" : [-7, 8]

  • "ship.type" : "Cargo Ship"

  • "ship.captains.name" : "Francis Drake"

  • "ship.captains.crew" : "first mate"

  • "ship.captains.crew" : "carpenter"

Wildcard indexes do not record the array position of any given element in an array during indexing. However, MongoDB may still use the wildcard index to fulfill a query that includes a field path with one or more explicit array indices.

For example, consider this document:

db.fleet.insertOne( {
"ship": {
"coordinates" : [
[-5, 10],
[-7, 8]
],
"type": "Cargo Ship",
"captains": [
{
"name": "Francis Drake",
"crew": [ "first mate", "carpenter" ]
}
]
}
} )

Create a wildcard index that includes the ship field:

db.fleet.createIndex( { "ship.$**": 1 } )

The index records for ship.coordinates and ship.captains do not include the array position for each element. Wildcard indexes ignore array element positions when recording the element into the index. However, wildcard indexes can still support queries that include explicit array indices.

MongoDB can use the wildcard index to fulfill this query:

db.fleet.find( { "ship.captains.0.name": "Francis Drake" } )

The query returns the sample document:

[
{
_id: ObjectId("6350537db1fac2ee2e957efc"),
ship: {
coordinates: [ [ -5, 10 ], [ -7, 8 ] ],
type: 'Cargo Ship',
captains: [
{ name: 'Francis Drake', crew: [ 'first mate', 'carpenter' ] }
]
}
}
]

MongoDB cannot use the wildcard index to fulfill this query:

db.fleet.find( { "ship.coordinates.0.1": 10 } )

The ship.coordinates field contains embedded arrays. Wildcard indexes do not record individual values of embedded arrays. Instead, they record the entire embedded array. As a result, the wildcard index cannot support a match on an embedded array value, and MongoDB fulfills the query with a collection scan.

MongoDB can only use a wildcard index to fulfill a given field path in the query if the path contains 8 or fewer explicit array indices. If the field path contains more than 8 explicit indices, to fulfill the query, MongoDB either:

  • Selects another eligible index.

  • Performs a collection scan.

Wildcard indexes themselves do not have limits on the depth to which they traverse a document while indexing it. The limitation only applies to queries which explicitly specify exact array indices.

← Wildcard Indexes Reference