web-dev-qa-db-ja.com

ループバックで自動移行する方法

ループバックアプリケーションでいくつかのモデルとテーブルの名前を変更しましたが、このモデル定義に移行する必要があります。

autoMigrate() を実行する必要があります。 dataSourceオブジェクトで実行する必要がありますが、ドキュメントにはこれらのいずれかを取得するためのヘルプはありません。

これまでのところ、/bootに次のものを含む新しいスクリプトを作成しました。

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

ただし、このデータソースオブジェクトにはautoMigrate関数が含まれていません。

そこにある自動移行ボタンを使用するためにstronglooparcを実行しようとしましたが、次のエラーでページがクラッシュします。

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)

モデルを更新するだけで、なぜこれが難しいのかわかりません。誰かがこれらの障害を克服する方法を知っていますか?ありがとう!

9
JD.

2つの問題。

まず、問題がサーバー側にあるのに、Angularクライアント側エラーが表示されています。

ここで、問題の核心に戻ります。

ブートスクリプトは、同期ブートスクリプトの場合はループバックオブジェクト(サーバー)のみ、またはループバックオブジェクトとコールバック(非同期ブートスクリプトの場合)のいずれかを受け入れる単一の関数をエクスポートする必要があります。

ブートスクリプトの記述が文書化されています ここ

関数 datasource.automigrate は同期的に呼び出すことができます。 パラメーターなしで呼び出すと、デフォルトでアプリ内のすべてのモデルに対して実行されます。これはおそらくあなたが望むものです。

したがって、定義したデータベースの名前がmysql./server/datasources.jsonで定義)の場合、ブートスクリプトは次のようになります。

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

これが機能することを確認するには、ブラウザでnode .[〜#〜] not [〜#〜]を実行します。サーバーがリッスンしているアドレス。 (Angular関連のエラーはブートスクリプトとは関係ありません。クライアント側のファイルに関連しており、おそらくclientフォルダーにあります)。

ターミナルに表示されます

Performed automigration.
14
Overdrivr

私は本当に好きでした JeséRodríguezの答え 各モデルで一度に1つずつ自動更新を実行するので、どのモデルが更新されたかを知ることができます。残念ながら、それはapp.modelを繰り返し処理しますが、これは正しくなく、 いくつかの負の副作用が発生する可能性があります

これが私のバージョンです(非同期/待機には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();
    });
  });
}
1
bmaupin

ブートスクリプト内では、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

1

Binディレクトリのサーバーフォルダに新しいファイル(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: '[email protected]',
      address: "asdasd"
    },
    {
      name: '[email protected]',
      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();
    });
  });
});

コードソース:ループバックgithubリポジトリ。

0
Irtiza