Docs Menu

Docs HomeDevelop ApplicationsMongoDB Manual

Maintain Different Schema Versions

On this page

  • About this Task
  • Before you Begin
  • Steps
  • Add a schemaVersion field to the collection
  • Insert a document with an updated schema
  • Next Steps
  • Query the Collection
  • Update a Document in the Collection
  • Learn More

Your application's schema requirements may change over time. For example, when new services become available, you may need to add new fields to your documents. MongoDB's flexible data model means that you can use a non-uniform document structure throughout your collection, and you can retain your older document structure alongside the updated schema.

The Schema Versioning Pattern lets you have different versions of your schema in the same collection, which avoids large-scale schema migrations when requirements change.

If you have a field that appears at different levels in your documents, the Schema Versioning Pattern may affect your indexes. For example, if you store the same field as both a top-level field and as an embedded field in different documents, you may need multiple indexes to support queries on that field.

In the following example, an online store uses a collection to track customer contact information. At first, the collection only contains home and work phone numbers. Over time, new contact methods are added and some older methods aren't needed.

Insert the sample document:

db.contacts.insertOne(
{
_id: 1,
name: "Taylor",
home: "209-555-7788",
work: "503-555-0110"
}
)

The following procedure sets the initial schema version for the collection, then inserts a new document with a different schema.

1

To differentiate between different schemas in the collection, add a schemaVersion field.

The following command adds a schemaVersion field with the value 1 to the documents with the initial schema:

db.contacts.updateMany(
{ },
{
$set: { schemaVersion: 1 }
}
)
2

In the updated schema, customers can link their social media accounts. Insert a document that accounts for the new requirements and has a schemaVersion of 2:

db.contacts.insertOne(
{
_id: 2,
schemaVersion: 2,
name: "Cameron",
contactInfo: {
cell: "903-555-1122",
work: "670-555-7878",
instagram: "@camcam9090",
linkedIn: "CameronSmith123"
}
}
)

After you implement the Schema Versioning Pattern, you need to modify how your application queries and updates data.

Now that there are two different schemas in the contacts collection, your query must check all possible locations for a field value depending on the document's schema version.

The following query searches based on the customer's work number. The query checks both possible locations for the work field:

db.contacts.find(
{
$or: [
{
work: "503-555-0110"
},
{
"contactInfo.work": "503-555-0110"
}
]
}
)

Output:

{
_id: 1,
name: 'Taylor',
home: '209-555-7788',
work: '503-555-0110',
schemaVersion: 1
}

Similar to inserting data, when you update a collection, your application must check all possible locations for the field to be updated. When you update data, you can use the schemaVersion field to determine the field to update.

To update the work phone number for the user with _id: 2, run this command:

db.contacts.updateOne(
{ _id: 2 },
[
{
$set: {
"work": {
$cond: {
if: { $eq: [ "$schemaVersion", 1 ] },
then: "999-999-9999",
else: null
}
},
"contactInfo.work": {
$cond: {
if: { $eq: [ "$schemaVersion", 2 ] },
then: "999-999-9999",
else: null
}
}
}
}
]
)

In the previous example:

  • If the matched document's schemaVersion is 1, then the work field is set to the updated value.

  • If the matched document's schemaVersion is 2, then the contactInfo.work field is set to the updated value.

← Keep a History of Document Versions