4

I'm using the Loopback API framework, pretty new to it.

I have an existing model that was previously created by Loopback, let's call it OldModelName. I want to rename it to NewModelName.

I already have existing data and multiple other models already reference it:

related-model.json

  "relations": {
    "oldModel": {
      "type": "belongsTo",
      "model": "OldModelName",
      "foreignKey": ""
    }
  }

What is the best way to rename/refactor a model without losing data? I don't think the best way is to login to Mongo shell and rename everything by hand, but I can't dig up anything that would tell me otherwise.

Andre D
  • 73
  • 6
  • 1
    No easy way... you just have to go through all of the config files and update it. – Jordan Kasper Jan 28 '16 at 13:50
  • Thanks Jakerella. I assume that I need to also modify the relationships in the database? For example if RelatedModel belongsTo OldModelName, then I have to apply this to all documents of RelatedModel: $rename { "oldModelNameId": "newModelNameId" } ? Or I guess another way to solve this would be to modify the foreignKey in related-model.json such that it resembles the old name? – Andre D Jan 28 '16 at 18:10

2 Answers2

1

Putting my previous comment in an answer and adding a little more...

There is no easy way to do this, you just need to go through all config files and update the name. (That includes those in common/models but also server/model-config.json and anywhere else you reference the model by name)

If you already have data persistently stored, then you have a bigger problem. If it's MySQL, for example, you need to rename the foreign key fields and update any FK restriction or triggers. If it's Mongo, you're going to need to sweep related connections to rename that FK object property.

Alternatively, you can keep the DB structure and just rename the model on the LoopBack side of things, but you would still need to use a custom foreign key name in LoopBack and update the model config with data source specific options.

Jordan Kasper
  • 13,153
  • 3
  • 36
  • 55
  • Thanks! I had a suspicion that I would need to do all this. Just wanted to confirm there wasn't a better way before I go ripping apart the database. Serves me right for not naming it something sane in the first place. Cheers! – Andre D Jan 28 '16 at 18:42
  • Please can you have a look at my question here ; http://stackoverflow.com/questions/39528371/loopback-error-authorization-required – shireef khatab Sep 16 '16 at 09:56
1

I have finally got the guts to do this and here are the steps I took:

  1. Back up the database
  2. Kill the server
  3. Edit model-config.json
  4. Edit the model definition JSON and model JS (old-model.json & old-model.js). Be sure to rename them to new-model.json, etc
  5. Edit all relations/related models
  6. Edit all boot scripts/operation hooks/etc

Now that the Loopback code has been updated, the Mongo DB must be updated accordingly:

mongo>

//Make sure the new collection we are migrating to is empty
db.NewCollection.drop();

//Copy all entries from OldCollection to NewCollection
db.OldCollection.find().forEach( function(x){db.NewCollection.insert(x)} );

//Update relations, for hasOne related models
db.RelatedCollection.update( {}, { $rename: { 'oldCollectionId': 'newCollectionId'} }, { multi: true} );

//Update relations, for hasAndBelongsToMany related models
db.NewCollectionRelatedCollection.drop();
db.OldCollectionRelatedCollection.find().forEach( function(x){db.NewCollectionRelatedCollection.insert(x)} );
db.NewCollectionRelatedCollection.update( {}, { $rename: { 'oldCollectionId': 'newCollectionId'} }, { multi: true} );

//Feeling confident?
db.OldCollection.drop();
db.OldCollectionRelatedCollection.drop();

Little nervewracking, but after taking these steps and restarting the server, everything worked fine, save for a few places I forgot to change the naming. This was my first time "refactoring" something in a database and hopefully I have overlooked a much easier way to do this, but this is the best I've come up with so far.

Andre D
  • 73
  • 6