5

次のような配列からデータベースをシードしています(単語と定義は多対多の関係にあります):

var seeds = [
{
    "word": "Click",
    "definitions": ["Computer", "Mouse", "Tasto", "Pulsante", "Selezionare"]
}, {
    "word": "Galoppo",
    "definitions": ["Cavallo", "Andatura", "Trotto", "Ippica", "Passo"]
}, {
    "word": "Raggio",
    "definitions": ["Sole", "Bicicletta", "Diametro", "Luce", "Laser"]
}, {
.
.
.goes on for 1089 objects

これは私が試したものです:

exports.seed = function (knex, Promise) {
var promises = seeds.map(function (seed) {
    return knex('words').insert({
        word: seed.word
    }, 'id').then(function (word_id) {
        var promises = seed.definitions.map(function (definition) {
            return knex('definitions').insert({
                definition: definition
            }, 'id').catch(function (err) {
                if (err.code === 1062)
                    return knex('definitions').select('id').where({
                        definition: definition
                    }).then(function (duplicate) {
                        return knex('definitions_words').insert({
                            definition_id: duplicate[0].id,
                            word_id: word_id
                        });
                    });
            }).then(function (definition_id) {
                return knex('definitions_words').insert({
                    definition_id: definition_id,
                    word_id: word_id
                });
            });
        });
        return Promise.all(promises);
    });
});
return Promise.all(promises);
};

単語はシード内で一意ですが、定義が繰り返される可能性があるため、重複エラーをキャッチし、重複の ID を取得してジャンクション テーブルに配置します。正常に動作しているように見えますが、ジャンクション テーブルは実際には 1089*5 行 (5445) になりますが、cli でエラーが発生します。

Error: Cannot add or update a child row: a foreign key constraint fails 
(`mytable`.`definitions_words`,
CONSTRAINT `definitions_words_definition_id_foreign`
FOREIGN KEY (`definition_id`) REFERENCES `definitions` (`id`))
4

1 に答える 1

0

あなたの移行を見ることはできませんが (これはかなり古い質問です)、通常、これらの外部キー制限で何が起こっているかは、 to referenceで定義definition_idしたことです。このため、参照する が存在する前にを作成することはできません。wordsdefinitions.idworddefinition

それをテストせずに、エラーチェックをせずに、次のようなものを使用することを想像します:

exports.seed = function (knex, Promise) {
  var promises = seeds.map(function (seed) {
    // Check for an existing definition. More recently
    // you can use `whereNotExists` but you always need
    // an id here whatever the case
    return knex('definitions')
      .select('id')
      .where('definition', seed.definition)
      .then(function (definition_id) {
        if (definition_id.length === 1) return definition_id[0]
        return knex('definitions')
          .insert({ definition: definition })
      })
      .then(function (definition_id) {
        // Use the definition once it exists
        return knex('words')
          .insert({ word: seed.word, definition_id: definition_id })
          .then(function (word_id) {
            return { word_id: word_id, definition_id: definition_id }
          });
      })
      .then(function (join_ids) {
        // Finally, update the join table
        return knex('definitions_words')
          .insert({
            definition_id: join_ids.definition_id,
            word_id: join_ids.word_id
          })
      })

  return Promise.all(promises);
};
于 2017-12-14T06:17:32.280 に答える