sql >> Base de Datos >  >> NoSQL >> MongoDB

Intentando hacer un upsert masivo con Mongoose. ¿Cuál es la forma más limpia de hacer esto?

([email protected] , [email protected] )

TL;RD

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

Larga historia:

Después de luchar con la documentación deficiente de la API de Mongoose , resolví el upsert masivo ajustando updateOne:{} operación en bulkWrite() método.

Un par de cosas no documentadas a considerar:

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

Las dos cosas clave aquí son problemas de documentación API incompleta (al menos en el momento de escribir este artículo):

  • 'upsert': true en cada documento . Esto no está documentado en Mongoose API (), que a menudo se refiere a node-mongodb-native conductor. Mirando updateOne en este controlador , podría pensar en agregar 'options':{'upsert': true} , pero, no... eso no funcionará. También traté de agregar ambos casos a bulkWrite(,[options],) argumento, sin ningún efecto tampoco.
  • GasStation.collection.bulkWrite() . Aunque método Mongoose bulkWrite() afirma que debería llamarse Model.bulkWrite() (en este caso, GasStation.bulkWrite() ), que activará MongoError: Unknown modifier: $__ . Entonces, Model.collection.bulkWrite() debe usarse.

Además, tenga en cuenta:

  • No necesitas usar el $set operador mongo en updateOne.update campo, ya que mongoose lo maneja en caso de upsert (ver bulkWrite() comentarios en el ejemplo ).
  • Tenga en cuenta que mi índice único en el esquema (necesario para que upsert funcione correctamente) se define como:

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

Espero que ayude.

==> EDITAR:(¿Mangosta 5?)

Como notó @JustinSmith, el $set El operador agregado por Mongoose ya no parece funcionar. ¿Tal vez sea por Mongoose 5?

En cualquier caso, usando $set debería hacer explícitamente:

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