2014-12-05 3 views
5

sto seminando il mio db da un array che assomiglia a questo (le parole e le definizioni sono in una relazione molti a molti):Knex migrazione semina completata con l'errore di chiave esterna

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 

Questo è quello che ho provato:

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); 
}; 

le parole sono unici nel mio semi, ma le definizioni possono ripetere, in modo da intercettare l'errore di duplicazione e afferrare l'id del duplicato di mettere che nella tabella di giunzione. Sembra funzionare bene, la tabella di collegamento, infatti, finisce con 1089 * 5 righe (5445), ma ottengo un errore sul 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`)) 

risposta

0

Anche se non siamo in grado di vedere i vostri migrazioni (e questo è una domanda piuttosto vecchia) quello che succede di solito con queste restrizioni di chiave esterna è che hai definito definition_id in words come riferimento definitions.id. Per questo motivo, non è possibile creare word prima che i riferimenti di definition esista.

senza prove, e spoglio di controllo degli errori, mi immagino che si utilizza qualcosa di più simile a questo:

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); 
};