MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

Essayer de faire un upsert en vrac avec Mongoose. Quelle est la manière la plus propre de faire cela ?

([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... */
]);

Longue histoire :

Après avoir lutté avec la mauvaise documentation de l'API Mongoose , j'ai résolu le upsert en masse peaufiner updateOne:{} opération dans bulkWrite() méthode.

Quelques éléments non documentés à prendre en compte :

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

Les deux éléments clés ici sont des problèmes de documentation d'API incomplète (au moins au moment de la rédaction) :

  • 'upsert': true dans chaque document . Ceci n'est pas documenté dans l'API Mongoose (), qui fait souvent référence à node-mongodb-native chauffeur. En regardant updateOne dans ce pilote , vous pourriez penser à ajouter 'options':{'upsert': true} , mais non... ça ne va pas. J'ai également essayé d'ajouter les deux cas au bulkWrite(,[options],) argument, sans effet non plus.
  • GasStation.collection.bulkWrite() . Bien que Méthode Mongoose bulkWrite() prétend qu'il devrait s'appeler Model.bulkWrite() (dans ce cas, GasStation.bulkWrite() ), qui déclenchera MongoError: Unknown modifier: $__ . Donc, Model.collection.bulkWrite() doit être utilisé.

De plus, notez :

  • Vous n'avez pas besoin d'utiliser le $set opérateur mongo dans updateOne.update champ, car la mangouste le gère en cas d'upsert (voir les commentaires bulkWrite() dans l'exemple ).
  • Notez que mon index unique dans le schéma (nécessaire pour que l'upsert fonctionne correctement) est défini comme suit :

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

J'espère que ça aide.

==> MODIFIER :(Mongoose 5 ?)

Comme l'a remarqué @JustinSmith, le $set L'opérateur ajouté par Mongoose ne semble plus fonctionner. C'est peut-être à cause de Mongoose 5 ?

Dans tous les cas, en utilisant $set devrait explicitement faire :

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