如何在Loopback中自动迁移

时间:2016-10-13 20:10:48

标签: loopbackjs strongloop loopback

我已在环回应用程序中重命名了许多模型和表格,但是现在我必须迁移到此模型定义。

我需要运行autoMigrate()。它必须在dataSource对象上运行,但文档没有提供有关获取其中一个的帮助。

到目前为止,我已在/boot中创建了一个包含以下内容的新脚本:

var loopback = require('loopback');
var app = module.exports = loopback();
app.loopback.DataSource.automigrate()

但此数据源对象不包含autoMigrate函数...

我已尝试运行strongloop arc以使用其中的自动迁移按钮,但页面崩溃时出现此错误:

Uncaught Error: [$injector:modulerr] Failed to instantiate module Arc due to:
Error: [$injector:modulerr] Failed to instantiate module Metrics due to:
Error: [$injector:nomod] Module 'Metrics' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument.
http://errors.angularjs.org/1.3.20/$injector/nomod?p0=Metrics
    at http://localhost:56073/scripts/vendor/angular/angular.js:63:12
    at http://localhost:56073/scripts/vendor/angular/angular.js:1778:17
    at ensure (http://localhost:56073/scripts/vendor/angular/angular.js:1702:38)
    at module (http://localhost:56073/scripts/vendor/angular/angular.js:1776:14)
    at http://localhost:56073/scripts/vendor/angular/angular.js:4131:22
    at forEach (http://localhost:56073/scripts/vendor/angular/angular.js:326:20)
    at loadModules (http://localhost:56073/scripts/vendor/angular/angular.js:4115:5)
    at http://localhost:56073/scripts/vendor/angular/angular.js:4132:40
    at forEach (http://localhost:56073/scripts/vendor/angular/angular.js:326:20)
    at loadModules (http://localhost:56073/scripts/vendor/angular/angular.js:4115:5)
http://errors.angularjs.org/1.3.20/$injector/modulerr?p0=Metrics&p1=Error%3…F%2Flocalhost%3A56073%2Fscripts%2Fvendor%2Fangular%2Fangular.js%3A4115%3A5)
    at http://localhost:56073/scripts/vendor/angular/angular.js:63:12
    at http://localhost:56073/scripts/vendor/angular/angular.js:4154:15
    at forEach (http://localhost:56073/scripts/vendor/angular/angular.js:326:20)
    at loadModules (http://localhost:56073/scripts/vendor/angular/angular.js:4115:5)
    at http://localhost:56073/scripts/vendor/angular/angular.js:4132:40
    at forEach (http://localhost:56073/scripts/vendor/angular/angular.js:326:20)
    at loadModules (http://localhost:56073/scripts/vendor/angular/angular.js:4115:5)
    at createInjector (http://localhost:56073/scripts/vendor/angular/angular.js:4041:11)
    at doBootstrap (http://localhost:56073/scripts/vendor/angular/angular.js:1455:20)
    at bootstrap (http://localhost:56073/scripts/vendor/angular/angular.js:1476:12)
http://errors.angularjs.org/1.3.20/$injector/modulerr?p0=Arc&p1=Error%3A%20…%2Flocalhost%3A56073%2Fscripts%2Fvendor%2Fangular%2Fangular.js%3A1476%3A12)

我只需要更新模型,并且不明白为什么这么难。有人知道如何克服这些障碍吗?谢谢!

4 个答案:

答案 0 :(得分:13)

两个问题。

首先,您正在显示Angular客户端错误,而您的问题出在服务器端。

现在,回到问题的核心。

启动脚本必须导出单个函数,在同步启动脚本的情况下,它只接受环回对象(您的服务器),或者回送对象和回调(对于异步启动脚本)。

记录编写引导脚本here

可以同步调用函数datasource.automigrate如果您在没有参数的情况下调用它,默认情况下会为您应用中的所有模型执行,这很可能是您想要的。

因此,如果您定义的数据库名称为mysql(在./server/datasources.json中定义),则启动脚本为:

module.exports = function (app) {
   app.dataSources.mysql.automigrate();
   console.log("Performed automigration.");
}

您可以通过浏览服务器正在侦听的地址浏览浏览器来运行node . NOT 来检查是否有效。 (与Angular相关的错误与启动脚本无关,它与客户端文件有关,很可能位于client文件夹中)。

它应该显示在终端

Performed automigration.

答案 1 :(得分:1)

您需要在启动脚本中使用app.dataSources.<dataSourceName>而不是app.loopback.DataSource

在启动脚本中尝试此操作:

module.exports = function (app) {
'use strict'
var mysql = app.dataSources.mysql;

console.log('-- Models found:', Object.keys(app.models));

for (var model in app.models) {
    console.log("Cheking if table for model " + model + " is created and up-to-date in DB...");
    mysql.isActual(model, function (err, actual) {
        if (actual) {
            console.log("Model " + model + " is up-to-date. No auto-migrated.");
        } else {
            console.log('Difference found! Auto-migrating model ' + model + '...');
            mysql.autoupdate(model, function () {
                console.log("Auto-migrated model " + model + " successfully.");
            });
        }
    });
} };

您可以在GitHub上看到我的基本示例:https://github.com/jeserodz/loopback-models-automigration-example

答案 2 :(得分:1)

我真的很喜欢Jesé Rodríguez's answer一次在每个模型上运行一次自动更新,因此我可以知道哪些模型已更新。不幸的是,它在app.modelcan have some negative side effects上进行了迭代。

这是我的版本(异步/等待需要Node 8 +):

'use strict';

// Update (or create) database schema (https://loopback.io/doc/en/lb3/Creating-a-database-schema-from-models.html)
// This is effectively a no-op for the memory connector
module.exports = function(app, cb) {
  updateDatabaseSchema(app).then(() => {
    process.nextTick(cb);
  });
};

async function updateDatabaseSchema(app) {
  const dataSource = app.dataSources.db;

  for (let model of app.models()) {
    if (await doesModelNeedUpdate(dataSource, model.modelName) === true) {
      await updateSchemaForModel(dataSource, model.modelName);
    }
  }
}

function doesModelNeedUpdate(dataSource, model) {
  return new Promise((resolve, reject) => {
    dataSource.isActual(model, (err, actual) => {
      if (err) reject(err);
      resolve(!actual);
    });
  });
}

function updateSchemaForModel(dataSource, model) {
  return new Promise((resolve, reject) => {
    dataSource.autoupdate(model, (err, result) => {
      if (err) reject(err);
      console.log(`Autoupdate performed for model ${model}`);
      resolve();
    });
  });
}

答案 3 :(得分:0)

在bin目录的server文件夹中创建一个新文件(automigrate.js),并将以下代码粘贴到该文件中。在这里,我使用cassandra作为数据源并在表中插入虚拟数据。您可以将此代码用于不同的数据源。根据您自己的要求更改表架构。

var path = require('path');
var app = require(path.resolve(__dirname, '../server/server'));
var ds = app.datasources.cassandra;
ds.automigrate('dataSourceTesting', function(err) {
  if (err) throw err;

  var accounts = [
    {
      name: 'john.doe@ibm.com',
      address: "asdasd"
    },
    {
      name: 'jane.doe@ibm.com',
      address: "asdasdasd"
    },
  ];
  var count = accounts.length;
  accounts.forEach(function(account) {
    app.models.dataSourceTesting.create(account, function(err, model) {
      if (err) throw err;

      console.log('Created:', model);

      count--;
      if (count === 0)
        ds.disconnect();
    });
  });
});

代码源:loopback github存储库。