Knex.js Миграции копируют существующие данные в другую таблицу

Можно ли с помощью миграции Knex.js копировать данные из одной таблицы в другую?

Вариант использования следующий: у меня есть таблица A, которую я хочу разделить на две новые таблицы B и C. В идеале я бы перебрал строки в A, чтобы создать соответствующие строки в B и C и заполнить их правильная информация.

Можно ли это сделать внутри файла миграции? Если исходить из этого вопроса, я считаю, что этот способ миграции в Node.JS довольно сложен (например, по сравнению с ActiveRecord). Есть ли лучший, более управляемый способ сделать такие миграции? Или это отраслевой стандарт?

2 ответа

Решение

Нет ничего особенного в объекте построителя запросов, переданном вашему up а также down функции внутри файла миграции. Вы можете использовать его так же, как и любой другой экземпляр построителя запросов в своем приложении, то есть запускать любые запросы, которые вы хотите в рамках миграции.

Вот очень простой пример. Учитывая, что у вас есть таблица с именем account с 4 полями, 1 из которых вы хотите разделить на таблицу:

// Starting promise chain with Promise.resolve() for readability only
exports.up = function(knex, Promise) {
  return Promise.resolve()
    .then(() => knex.schema.createTable('table_b', t => {
      t.string('col_a')
      t.string('col_b')
    }))
    .then(() => knex.schema.createTable('table_c', t => {
      t.string('col_c')
      t.string('col_d')
    }))
    .then(() => knex('table_a').select('col_a', 'col_b'))
    .then((rows) => knex('table_b').insert(rows))
    .then(() => knex('table_a').select('col_c', 'col_d'))
    .then((rows) => knex('table_c').insert(rows))
    .then(() => knex.schema.dropTableIfExists('table_a'))
};

exports.down = function(knex, Promise) {
  return Promise.resolve()
    .then(() => knex.schema.createTable('table_a', t => {
      t.string('col_a')
      t.string('col_b')
      t.string('col_c')
      t.string('col_d')
    }))
    .then(() => knex('table_b').select('col_a', 'col_b'))
    .then((rows) => knex('table_a').insert(rows))
    .then(() => knex('table_c').select('col_c', 'col_d'))
    .then((rows) => knex('table_a').insert(rows))
    .then(() => knex.schema.dropTableIfExists('table_b'))
    .then(() => knex.schema.dropTableIfExists('table_c'))
};

В этом случае вы также можете просто сохранить table_a и вместо создания третьей таблицы просто отбросьте два столбца и переименуйте таблицу. Имейте в виду, однако, что такое разделение вашей таблицы станет грязным, если она уже имеет отношения к другим таблицам в БД.

Насколько я понимаю, миграция имеет дело только с выполнением операций CRUD в таблицах.

knex позволяет вам вызывать функцию после завершения миграции:

`knex.migrate.latest()
.then(function() {
  return knex.seed.run();
})
.then(function() {
  // migrations are finished
});` 

Таким образом, вы можете добавить свой код в исходный файл или просто как функцию, как показано на рисунке.
Обратите внимание, что эта функция вызывается только после завершения миграции, что означает, что ваша таблица A все еще должна присутствовать (не может быть удалена).
Вот соответствующая документация

Другие вопросы по тегам