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

mangosta:detecta si el documento insertado es un duplicado y, de ser así, devuelve el documento existente

Si bien su código no maneja algunos casos de error y usa el find incorrecto función, el flujo general es típico dando el trabajo que desea hacer.

  1. Si hay otros errores además del duplicado, no se llama a la devolución de llamada, lo que probablemente cause problemas posteriores en su aplicación NodeJs
  2. use findOne en lugar de find ya que solo habrá un resultado dado que la clave es única. De lo contrario, devolverá una matriz.
  3. Si su devolución de llamada esperaba el tradicional error como primer argumento, puede pasar directamente la devolución de llamada a findOne función en lugar de introducir una función anónima.
  4. También puede consultar findOneAndUpdate eventualmente, dependiendo de cuál será su esquema y lógica finales.

Como se mencionó, es posible que pueda usar findOneAndUpdate , pero con costo adicional.

function save(id, title, callback) {
    Value.findOneAndUpdate(
       {id: id, title: title}, /* query */
       {id: id, title: title}, /* update */
       { upsert: true}, /* create if it doesn't exist */
       callback);
}

Todavía hay una devolución de llamada, por supuesto, pero volverá a escribir los datos si se encuentra el duplicado. Si eso es un problema realmente depende de los casos de uso.

He realizado una pequeña limpieza de su código... pero en realidad es bastante simple y la devolución de llamada debería ser clara. La callback a la función siempre recibe el documento recién guardado o el que coincidió como un duplicado. Es responsabilidad de la función que llama a saveNewValue para verificar si hay un error y manejarlo adecuadamente. Verá cómo también me aseguré de que la devolución de llamada se llame independientemente del tipo de error y siempre se llame con el resultado de manera coherente.

function saveNewValue(id, title, callback) {
    if (!callback) { throw new Error("callback required"); }
    var thisValue = new models.Value({
        id:id,
        title:title //this is a unique value
    });

    thisValue.save(function(err, product) {
        if (err) {
            if (err.code === 11000) { //error for dupes
                return models.Value.findOne({title:title}, callback);
            }            
        }    
        callback(err, product);
    });
}

Alternativamente, puede usar la promesa patrón. Este ejemplo usa when.js .

var when = require('when');

function saveNewValue(id, title) {
    var deferred = when.defer();

    var thisValue = new models.Value({
        id:id,
        title:title //this is a unique value
    });

    thisValue.save(function(err, product) {
        if (err) {
            if (err.code === 11000) { //error for dupes
                return models.Value.findOne({title:title}, function(err, val) {
                    if (err) {
                        return deferred.reject(err);
                    }
                    return deferred.resolve(val);
                });
            }
            return deferred.reject(err);
        }
        return deferred.resolve(product);
    });

    return deferred.promise;
}

saveNewValue('123', 'my title').then(function(doc) {
    // success
}, function(err) {
    // failure
});