What's the best practice (or tool) for updating/migrating Mongoose schemas as the application evolves?
There's nothing built into Mongoose regarding migrating existing documents to comply with a schema change. You need to do that in your own code, as needed.
Collections in MongoDB do not have a fixed schema, or requirement for all documents in a collection to have the same schema. You can definitely add or remove fields, change field types, or update JSON Schema validation without recreating a collection.
The $set operator replaces the value of a field with the specified value.
Everything in Mongoose starts with a Schema. Each schema maps to a MongoDB collection and defines the shape of the documents within that collection.
We don't really have to do a schema change, but we do need to update each document. MongoDB however does not allow you to update fields according to the value of other fields so we can not simply do a: Although you can retrieve the data like this through the Aggregation Framework: Note that I am abusing $concat here.
It is intended to migrate old schema versions of your documents as you use them, which is seems to be the best way to handle migrations in mongodb. You don't really want to run full dataset migrations on a document collection (ala alter table) as it puts a heavy load on your servers and could require application / server downtime.
You don't have to migrate anything, all you have to do is set the default value in the schema definition if the field is required. Show activity on this post. I just had this problem where I needed to update my database to reflect the changes to my schema.
A user actually suggested you use map reduce in MongoDB which would then allow you to use the java-script library of string functions. Harness technology creatively for a wondrous outcome. Good question. For your information, MongoDB stores documents in schema-less collections.
It's funny though, MongoDB was born to respond to the schema problems in RDBMS. You don't have to migrate anything, all you have to do is set the default value in the schema definition if the field is required.
new Schema({ name: { type: string } })
to:
new Schema({ name: { type: string }, birthplace: { type: string, required: true, default: 'neverborn' } });
Update: Tested, this does not work in its current form, its got the right idea going, I got a single migration to work with considerable tweaking of the module itself. But I don't see it working as intended without some major changes and keeping track of the different schemas somehow.
Sounds like you want mongoose-data-migrations
It is intended to migrate old schema versions of your documents as you use them, which is seems to be the best way to handle migrations in mongodb.
You don't really want to run full dataset migrations on a document collection (ala alter table) as it puts a heavy load on your servers and could require application / server downtime. Sometimes you may need to write a script which simply grabs all documents applies the new schema / alterations and calls save, but you need to understand when/where to do that. An example might be, adding migration logic to doc init has more of a performance hit than taking down the server for 3 hours to run migration scripts is worth.
I found this link pretty helpful as well, basically reiterates the above in more detail and essentially implements the above node package's concept in php.
N.B. The module is 5months old, 0 forks, but am looking around and can't find anything better / more helpful than abdelsaid's style of response..
I just had this problem where I needed to update my database to reflect the changes to my schema. After some research I decided to try the updateMany() function in the mongo console to make the updates and I think it worked pretty well.
To apply this to vimdude's example the code would look as follows:
try {
db.<collection>.updateMany( { birthplace: null }, { $set:
{"birthplace": "neverborn" } } );
} catch(e) {
print(e);
}
The updateMany() function will update all documents in a collection based on a filter. In this case the filter is looking for all documents where the field 'birthplace' is null. It then sets a new field in those documents named 'birthplace' and sets its value to 'neverborn'.
After running the code, modified to reflect your circumstances run:
db.<collection>.find().pretty()
to verify that the changes were made. The new field "birthplace" with the value of "neverborn" should show at the end of each document in your collection.
Hope that helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With