使用关联种子数据进行KnexJS迁移

时间:2015-12-25 18:46:07

标签: javascript mysql node.js bookshelf.js knex.js

我正在学习BookshelfJS / KnexJS(从SequelizeJS转换),我遇到了将数据导入多个表的问题,这些表是通过KnexJS中的迁移功能创建的。有4个表:

  1. servers
  2. operating_systems
  3. applications
  4. applications_servers
  5. 具有以下约束条件:

    • serversoperating_system_id引用operating_systemsid
    • applications_serversserver_id引用serversid
    • applications_serversapplication_id引用applicationsid

    当我运行knex migrate:latest --env development servers时,表格被创建得很好,当我将表格数据导入表格时出现错误。

    最初,我将4个表的种子数据组织到目录./seeds/dev中的4个不同文件中,这只是${table_name}.js

    1. operating_systems.js
    2. servers.js
    3. applications.js
    4. applications_servers.js
    5. 经过一些调试后,我意识到文件 applications_servers.js 中的种子数据时会产生错误,因为当我把那个拿出来时,另外3个运行正好。然后,当我删除3个种子文件并将 applications_servers.js 移动到 ./ seeds / dev / 目录并执行knex seed:run时, applications_servers < / em> table填充得很好。但是,当我尝试一次导入所有4个文件的种子数据时,我收到以下错误:

      # knex seed:run
      Using environment: development
      Error: ER_NO_REFERENCED_ROW_2: Cannot add or update a child row: a foreign key constraint fails (`bookshelf_knex_lessons`.`applications_servers`, CONSTRAINT `applications_servers_server_id_foreign` FOREIGN KEY (`server_id`) REFERENCES `servers` (`id`) ON DELETE CASCADE)
      at Query.Sequence._packetToError (/Users/me/Documents/scripts/js/node/bookshelf_knex/node_modules/mysql/lib/protocol/sequences/Sequence.js:48:14)
      at Query.ErrorPacket (/Users/me/Documents/scripts/js/node/bookshelf_knex/node_modules/mysql/lib/protocol/sequences/Query.js:83:18)
      

      并没有一行插入任何表格。

      我认为这可能与他们被导入的订单有关。 (因为它们必须按照上面列出的文件的顺序导入)。因此,考虑到它们可能以字母数字顺序引用,我将它们重命名为:

      1. 1-operating_systems.js
      2. 2- servers.js
      3. 3- applications.js
      4. 4- applications_servers.js
      5. 然而,没有任何改变,没有行插入任何表,所以只是为了确定,我颠倒了文件上的数字前缀的顺序,并且再次,没有更改,没有插入单行,并且同样的错误返回。

        注意:用于创建表的迁移脚本以及所有种子数据都是从我创建的JS文件中复制和粘贴的,该文件创建相同的表并使用BookshelfJS / KnexJS导入相同的数据,而不是使用迁移功能,它只是在通过节点执行时手动执行。您可以查看此文件 here

        任何帮助将不胜感激!

        编辑:当我将./seeds/dev中的所有种子文件合并到一个文件./seeds/dev/servers.js中时,所有内容都会被导入。这让我觉得它可能是由异步执行的knex迁移引起的,因此插入到数据透视表中的ID和serversoperating_system_id可能还没有插入到关联的表中...如果是这种情况,有没有办法在种子文件中设置依赖项?

2 个答案:

答案 0 :(得分:3)

Knex.js的种子功能不提供任何执行保证顺序。每个种子都应该写成可以单独执行 - 即。你的单一文件方法是正确的。

如果要将单个种子文件分解为子模块,则可以尝试以下操作:

// initial-data.js
var operatingSystems = require('./initial-data/operating-systems.js');
var servers = require('./initial-data/servers.js');
exports.seed = function(knex, Promise) {
  return operatingSystems.seed(knex, Promise)
  .then(function () {
    return servers.seed(knex, Promise);
  }).then(function() {
    // next ordered migration...
  });
}

答案 1 :(得分:0)

我使用sql-fixtures模块处理种子文件中的FK关系依赖项。

虚构实施:

const dataSpec = {
  applications_servers: [{
    name: 'My ASP.Net thingie',
    application_id: 'applications:0',
    server_id: 'servers:0'
  }],

  servers: [{
    name: 'My Windows server',
    operating_system_id: 'operating_systems:0'
  }],

  operating_systems: [{
    name: 'Windows Server 2k10'
  }],

  applications: [{
    name: 'My fab web guestbook',
    description: '...'
  }]
}

如果您通过ORM声明您的依赖项,则可能是多余的。

然而,有时需要避免将DB种子耦合到您当前的模型实现。