MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

mangusto:detecta se o documento inserido é duplicado e, em caso afirmativo, retorna o documento existente


Embora seu código não lide com alguns casos de erro e use o find errado função, o fluxo geral é típico dando o trabalho que você quer fazer.
  1. Se houver erros além da duplicata, o retorno de chamada não será chamado, o que provavelmente causará problemas de downstream em seu aplicativo NodeJs
  2. use findOne em vez de find pois haverá apenas um resultado, dado que a chave é única. Caso contrário, ele retornará uma matriz.
  3. Se seu retorno de chamada esperava o tradicional error como o primeiro argumento, você pode passar diretamente o retorno de chamada para o findOne função em vez de introduzir uma função anônima.
  4. Você também pode consultar findOneAndUpdate eventualmente, dependendo de qual será seu esquema e lógica finais.

Como mencionado, você pode usar findOneAndUpdate , mas com custo 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);
}

Ainda há um retorno de chamada, é claro, mas ele gravará os dados novamente se a duplicata for encontrada. Se isso é um problema realmente depende dos casos de uso.

Fiz uma pequena limpeza no seu código... mas é bem simples e o retorno de chamada deve estar claro. O callback para a função sempre recebe o documento recém-salvo ou aquele que foi correspondido como duplicado. É responsabilidade da função que chama saveNewValue para verificar se há um erro e tratá-lo adequadamente. Você verá como também garanti que o retorno de chamada seja chamado independentemente do tipo de erro e sempre seja chamado com o resultado de maneira consistente.
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);
    });
}

Como alternativa, você pode usar a promessa padronizar. Este exemplo está usando 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
});