MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

Sto cercando di fare un upsert di massa con Mongoose. Qual è il modo più pulito per farlo?

([email protected] , [email protected] )

TL;DR

await GasStation.collection.bulkWrite([ // <<==== use the model name
  {
    'updateOne': {
      'filter': { 'id': '<some id>' },
      'update': { '$set': { /* properties to update */ } },
      'upsert': true,  // <<==== upsert in every document
    }
  },
  /* other operations here... */
]);

Una lunga storia:

Dopo aver lottato con Documentazione scarsa dell'API Mongoose , ho risolto il upsert collettivo modifica di updateOne:{} operazione nel bulkWrite() metodo.

Un paio di cose non documentate da considerare:

// suppose:
var GasStation = mongoose.model('gasstation', gasStationsSchema);
var bulkOps = [ ];

// for ( ... each gasStation to upsert ...) {
  let gasStation = { country:'a', localId:'b', xyz:'c' };
  // [populate gasStation as needed]
  // Each document should look like this: (note the 'upsert': true)
  let upsertDoc = {
    'updateOne': {
      'filter': { 'country': gasStation.country, 'localId': gasStation.localId },
      'update': gasStation,
      'upsert': true
  }};
  bulkOps.push(upsertDoc);
// end for loop

// now bulkWrite (note the use of 'Model.collection')
GasStation.collection.bulkWrite(bulkOps)
  .then( bulkWriteOpResult => {
    console.log('BULK update OK');
    console.log(JSON.stringify(bulkWriteOpResult, null, 2));
  })
  .catch( err => {
    console.log('BULK update error');
    console.log(JSON.stringify(err, null, 2));
  });

Le due cose chiave qui sono problemi di documentazione API incompleta (al momento della scrittura, almeno):

  • 'upsert': true in ogni documento . Questo non è documentato in Mongoose API(), che spesso si riferisce a node-mongodb-native autista. Guardando updateOne in questo driver , potresti pensare di aggiungere 'options':{'upsert': true} , ma, no... non va bene. Ho anche provato ad aggiungere entrambi i casi a bulkWrite(,[options],) argomento, senza alcun effetto.
  • GasStation.collection.bulkWrite() . Sebbene metodo Mongoose bulkWrite() afferma che dovrebbe essere chiamato Model.bulkWrite() (in questo caso, GasStation.bulkWrite() ), che attiverà MongoError: Unknown modifier: $__ . Quindi, Model.collection.bulkWrite() deve essere utilizzato.

Inoltre, nota:

  • Non è necessario utilizzare il $set operatore mongo in updateOne.update campo, poiché mongoose lo gestisce in caso di upsert (vedi bulkWrite() nell'esempio ).
  • Nota che il mio indice univoco nello schema (necessario per il corretto funzionamento dell'upsert) è definito come:

gasStationsSchema.index({ country: 1, localId: 1 }, { unique: true });

Spero che aiuti.

==> MODIFICA:(Mangusta 5?)

Come notato da @JustinSmith, il $set l'operatore aggiunto da Mongoose non sembra funzionare più. Forse è a causa di Mongoose 5?

In ogni caso, utilizzando $set dovrebbe fare esplicitamente:

'update': { '$set': gasStation },