Mongoose: Método de atualização de modelo não respeita validadores

Criado em 24 abr. 2012  ·  59Comentários  ·  Fonte: Automattic/mongoose

Posso usar o método model.Update para atualizar para qualquer valor, independentemente das restrições de esquema

Por exemplo, se eu tiver um Schema com uma propriedade enum, usando update posso alterar para qualquer valor fora da restrição de enum, invalidando assim o conjunto.

O comportamento esperado era lançar um erro se o valor atualizado não fosse validado.

Eu sugiro uma opção extra para o método de atualização para sair no primeiro erro ou não.

new feature

Comentários muito úteis

+1

É completamente não intuitivo que a atualização não usaria: padrões, setters, validação e enums. Para que serve um esquema se as operações principais não aderem a ele.

Todos 59 comentários

você pode desejar habilitar a configuração de esquema strict que irá ignorar todos os caminhos de esquema inválidos e atualizar o resto. nenhum erro é lançado.

novo Esquema ({..}, {estrito: verdadeiro})

há uma solicitação pull semelhante aguardando para ser mesclada que é lançada ao definir caminhos que não existem no esquema, mas não é lançada durante model.update . talvez devêssemos adicionar isso ao PR acima e ter o erro passado para o retorno de chamada.

Olá de novo, obrigado pela sua resposta rápida.

Eu não estava me referindo a caminhos inválidos, mas à restrição dentro de um caminho específico.

Veja este exemplo

var User = new Schema ({
nome do usuário: {
tipo: String,
minúsculas: verdadeiro,
trim: true,
único: verdadeiro
},
nome: {
tipo: String,
trim: true,
obrigatório: verdadeiro,
único: falso,
índice: verdadeiro
},
senha: {
tipo: String,
obrigatório: verdadeiro,
selecione: falso,
set: encrypt
},
papel: {
tipo: String,
"usuário padrão',
"enum": ['usuário', 'admin', 'root']
},
criada: {
tipo: data,
"default": Date.now
}
}, {estrito: verdadeiro});

users.update ({"username": "test"}, {"role": "thisShowldFail"}, function (err, val) {
...
});

Observe que agora o usuário de "teste" tem a função "thisShowldFail", mesmo com a opção de esquema estrito habilitada.
O Update não deve respeitar enums e outras opções semelhantes?

Você está correto, ele deve validar enums. Achei que houvesse um ingresso para isso em algum lugar.

+1, não é possível usar #update por causa desse problema.

É possível deixar .update fazer todas as coisas que um novo documento + .save faria?

  • padrões
  • normatizador
  • validações personalizadas
  • enum

se a opção upsert for usada, também

  • obrigatório

não atualmente

Quer dizer, é possível / planejado implementar ...? :)

pode ser bom. relacionado # 472

+1

É completamente não intuitivo que a atualização não usaria: padrões, setters, validação e enums. Para que serve um esquema se as operações principais não aderem a ele.

+1

Eu amo o mangusto, mas se ele não valida as atualizações é muito menos útil para mim. Tenho documentos grandes e não quero baixá-los apenas para fazer a validação.

Este sou eu entrando. Estou dando um mergulho um pouco, tentando implementar isso.
O objetivo é obter:

  • padrões
  • normatizador
  • validações
  • enum
  • obrigatório

Nem tenho certeza se terei sucesso, mas vou dar uma chance. Vou começar com validadores.

Deseje-me boa sorte!

Merc.

+1

+1

Teria sido ótimo se .update suportasse validações.

Bump +1

Bumpy bump +1

Por favor, adicione validações na atualização!

+1

Edit: -2 porque eu não acho que o mongoose deve assumir a validação no comando .. Se você quiser validação, você deve considerar o uso de outra biblioteca especializada como uma que permite a validação do esquema JSON

@thalesfsp Sim. Já foi tentado no passado, mas as regras ficam muito confusas porque não existe nenhum documento na memória e se quebram em várias circunstâncias, deixando o comportamento inconsistente e confuso.

a beleza do código aberto: se você quiser um recurso, pode escrevê-lo e enviar uma solicitação de pull com aprovação em testes e documentação que prova que funciona corretamente.

Uma limitação muito séria. Ao buscar um patch, seria prático apenas rastrear o objeto Schema diretamente para determinar se um validador deve ser executado? Preocupo-me principalmente com validadores personalizados e regras enum aplicadas à atualização. As outras restrições de esquema já deveriam ter sido aplicadas quando o documento foi salvo, eu acho. Essa simplificação do problema para apenas enums e validadores faz sentido e remove a necessidade de ter qualquer documento por perto durante a atualização?

+1 Bump, este seria um recurso muito útil - ao fazer atualizações, gostaria de ver os min / maxes etc. respeitados no esquema - caso contrário, estou fazendo muita lógica clichê para algo que o mangusto pode fazer

Seria ótimo ver isso acontecer. No momento, minha solução alternativa é encontrar o objeto, alterar os campos e salvá-lo, o que dispara o middleware de validação. De acordo com os documentos :

Tank.findById(id, function (err, tank) {
  tank.size = 'large';
  tank.save(function (err) {
   // Document updated, do something with it
  });
});

Eu entendo que isso seja complicado, uma vez que o comando update delega diretamente para o Mongo e o documento completo não fica na memória para ser validado. Portanto, a abordagem sugerida por @BrianHoldsworth parece ser um bom lugar para começar, analisando as validações em execução do Schema apenas em relação aos campos que devem ser atualizados.

@aheckmann você poderia nos fornecer mais alguns detalhes sobre os esforços de implementação anteriores (com falha) para que quem tentar este patch não cometa os mesmos erros novamente?

Preocupo-me principalmente com validadores personalizados e regras enum aplicadas à atualização. As outras restrições de esquema já deveriam ter sido aplicadas quando o documento foi salvo, eu acho. Essa simplificação do problema para apenas enums e validadores faz sentido e remove a necessidade de ter qualquer documento por perto durante a atualização?

@BrianHoldsworth Acho que isso pode ser uma simplificação exagerada. O que acontece se um campo com uma restrição de validação required: true for atualizado para uma string vazia? Precisamos disso para disparar um erro de validação.

Também estou interessado nisso. Talvez um plug-in pudesse ser escrito para substituir o método .update () e executar a validação? Dessa forma, até mesmo uma solução parcial pode ser implementada. Por outro lado, se estivesse no núcleo, seria esperado que lidasse com todos os tipos de validação e fosse 100% robusto.

Eu também encontrei isso, com validadores personalizados e enums. Embora seja possível localizar e atualizar, é muito difícil escrever código de caso geral quando os documentos têm estruturas de sub-documentos diferentes.

+1 bump isto.

A solução de Brian parece muito elegante. Adoraria ser notificado quando os patches chegarem ao beta.

+1

preciso deste +1

+1

+1

+1

+1

Na 3.9.3 update() terá 2 opções especiais, setDefaultsOnInsert e runValidators , que definirá os padrões e executará validadores em sua consulta. Veja os testes, por exemplo, nenhum documento real ainda :(

Muito obrigado - esta é uma ótima solução!

@ vkarpov15 Usei seu código para também aplicar a validação para findOneAndUpdate. Consulte PR # 2393.

Olá, você sabe quando a versão estável 3.9 será lançada para usar a validação na atualização?

Obrigado

@AlexandreAWE boa pergunta. No momento, estou encerrando as coisas no 4.0 e testando a versão beta do branch 3.9.x, mas agora é uma coisa do tipo "estará pronto quando estiver pronto". Espero lançar um RC antes do Natal.

@ vkarpov15 Como está indo no estável 3.9.x? Seria ótimo ter validações na atualização em vez de encontrar e salvar todas as vezes para o meu projeto atual.

@andrewholsted esperando o driver mongodb 2.0 e o servidor mongodb 2.8 se estabilizarem - isso provavelmente acontecerá este mês, mas não pode realmente ser lançado 4.0 sem suportar a versão mais recente do mongodb e o driver mais recente. Veja meu blog para um pouco mais de detalhes.

Pergunta potencialmente idiota por mim, mas por que não pegar os dados que estão sendo atualizados e validá-los no esquema antes de passar para o mongodb?

Além disso, +1

marque e espere

Não posso esperar até que 3.9 esteja estável :)

Este recurso já está disponível? Esperando ansiosamente por 3.9 .. Quando estará disponível?

Você pode npm install mongoose@unstable para obter a versão instável. O ETA atual para 4.0 é 25 de março - um bom lugar para verificar esta é a página de marcos

Acabei de encontrar esse problema na noite passada. Que bom que não sou o único! Estou ansioso para que essa mudança seja lançada, obrigado por tudo que você faz!

+1

Não sei por que este problema está marcado como encerrado. Eu ainda estou enfrentando isso.

Na verdade, não tenho certeza se isso funciona na validação de enum para findOneAndUpdate (), mesmo com runValidators definido como true.

@ m1cah forneça um exemplo que demonstra o que você está tentando fazer. Temos testes para isso e eles passam ...

@ vkarpov15 Eu acredito que este é um pequeno exemplo que demonstra isso: http://code.runnable.com/VYhGbVhereIYdbst/update-validation-enum-for-mongoose-and-databases

Bem, um problema é que o exemplo acima está usando uma versão pré-histórica do mangusto:

root<strong i="6">@runnable</strong>:~# head node_modules/mongoose/package.json                                                                                                                 
{                                                                                                                                                                         
  "name": "mongoose",                                                                                                                                                     
  "description": "Elegant MongoDB object modeling for Node.js",                                                                                                           
  "version": "3.6.14",                                                                                                                                                    
  "author": {                                                                                                                                                             
    "name": "Guillermo Rauch",                                                                                                                                            
    "email": "[email protected]"                                                                                                                                   
  },                                                                                                                                                                      
  "keywords": [                                                                                                                                                           
    "mongodb",  

Tente atualizar para 4.xe deve funcionar.

Tem certeza de que funciona com um método enum e findOneAndUpdate?
No mangusto 4.2.6 parece falhar, posso definir um valor incorreto.

Esquema:

var UserSchema = new Schema({
    first_name: {
        type: String,
        required: true,
    },
    last_name: {
        type: String,
        required: true,
    },
    email: {
        type: String,
        unique: true,
        required: true,
    },
    embededData: [{
        type: {
            type: String,
            enum: ['value1', 'value2', 'value3']
            required: true
        }
    }]
}, { strict: true });

Método FindOneAndUpdate:

UserModel.findOneAndUpdate(
    {_id: uid}, 
    {$push: {embededData: data}}, 
    { runValidators: true }, function(err) {
});

Então posso empurrar embededData.type = 'Panda';

Veja a documentação do validador de atualização e # 2933 - validadores de atualização não funcionam em $push , apenas em $set e $unset

+1

Pelo que posso ver, isso ainda não funciona para o caso em que você está usando um validador personalizado em um campo que é uma matriz.

Por exemplo, este snippet de código:

var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/myTestDB');

var db = mongoose.connection;

db.on('error', function (err) {
console.log('connection error', err);
});
db.once('open', function () {
console.log('connected.');
});

var Schema = mongoose.Schema;
var userSchema = new Schema({
  _id : String,
  name : {
    type: [String],
    validate: {
        validator: function (str) {
            return str.length > 1
        }
    },
  }
});


var User = mongoose.model('User', userSchema);

User.findOneAndUpdate({"name": ["John", "Doe"]}, { 
  $setOnInsert: {
    name: ["John"],
  },
}, { runValidators: true, upsert: true, new: true }, function (err, data) {
  if (err) {
    return console.log(err);
  } else {
    // console.log(data.validateSync())
    return console.log('Updated', data);
  }
});

permitirá que você atualize o usuário para ter um campo name de ["John"] sem gerar nenhum erro, embora o validador personalizado que incluí proíba explicitamente qualquer matriz de nome de comprimento menor ou igual a 1. O O validador em si funciona bem, como pode ser visto pelo fato de que se você descomentar a linha console.log(data.validateSync()) , forçando assim a validação, ele retornará de fato a mensagem de erro apropriada. O problema é que essa validação não está ocorrendo dentro da chamada findOneAndUpdate() , apesar de eu incluir a opção runValidators=true .

Parece um bug. Você pode abrir um problema separado para isso?

Obrigado

Existe alguma correção disponível para o problema acima? @ vkarpov15

@ Saravanan90, por favor, pare de comentar sobre questões há muito fechadas, sem qualquer informação significativa. Abra um problema separado com exemplos de código.

Esta página foi útil?
0 / 5 - 0 avaliações