73

What's the best practice (or tool) for updating/migrating Mongoose schemas as the application evolves?

6

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..

1
  • 1
    Updated. Sadly its rather broken. Let me know here if you ever find anything, kind of want a suitable solution for the update as you go method. I have a feeling you'd need to keep track of each version in order to load older schemas and allow modifications like the module attempts to do. Alas, my mongoose knowledge is pretty lacking so far. Getting there! – Louis Feb 27 '14 at 11:12
38

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' }
});
16
  • 1
    I'm really thinking about tools like Rails' migrations which let you handle the change management aspects, but I don't think there really is anything like it, so I'll accept this. – mahemoff Jan 7 '12 at 21:33
  • 4
    I don't think it's so different to SQL databases. You might be splitting "name" into "firstname" and "surname" fields for example...you'd have to run that transformation against each environment's database and track it somehow. – mahemoff Jan 9 '12 at 11:56
  • 19
    You don't have to "migrate" the schema (well sort of, you might still migrate indexes etc in the absence of an actual schema), but you do have to migrate the actual data. – mahemoff Jan 12 '12 at 11:55
  • 2
    You're trying to fix history. You should use plugins instead. – vimdude Oct 29 '12 at 22:19
  • 3
    Ok, i have a me too, as I don't have this situation yet, but I have a VERY large schema that I know will need to change over time, so how do I access items in a collection that were created in a previous version of the schema? Is there magic in mongoose? – regretoverflow May 3 '13 at 19:44
7

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.