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

Mangosta error de clave duplicada con upsert

Un upsert que da como resultado la inserción de un documento no es una operación totalmente atómica. Piense en el upsert como realizando los siguientes pasos discretos:

  1. Consulta por el documento identificado a actualizar.
  2. Si el documento existe, actualice atómicamente el documento existente.
  3. De lo contrario (el documento no existe), inserte atómicamente un nuevo documento que incorpore los campos de consulta y la actualización.

Entonces, los pasos 2 y 3 son cada uno atómico, pero podría ocurrir otro upsert después del paso 1, por lo que su código debe verificar el error de clave duplicada y luego volver a intentar el upsert si eso ocurre. En ese momento, conoce el documento con ese _id existe por lo que siempre tendrá éxito.

Por ejemplo:

var minute = utils.minute();
Monitor.update({ _id: minute }, { $inc: update }, { upsert: true }, function(err) {
    if (err) {
        if (err.code === 11000) {
            // Another upsert occurred during the upsert, try again. You could omit the
            // upsert option here if you don't ever delete docs while this is running.
            Monitor.update({ _id: minute }, { $inc: update }, { upsert: true },
                function(err) {
                    if (err) {
                        console.trace(err);
                    }
                });
        }
        else {
            console.trace(err);
        }
    }
});

Consulte aquí la documentación relacionada.

Es posible que aún se pregunte por qué puede suceder esto si la inserción es atómica, pero eso significa que no se producirán actualizaciones en el documento insertado hasta que esté completamente escrito, no que no haya otra inserción de un documento con el mismo _id puede ocurrir.

Además, no necesita crear manualmente un índice en _id ya que todas las colecciones de MongoDB tienen un índice único en _id independientemente. Entonces puedes eliminar esta línea:

monitorSchema.index({_id: -1}); // Not needed