Exclua uma chave de um documento MongoDB usando Mongoose

103

Estou usando a Biblioteca Mongoose para acessar MongoDB com node.js

Existe uma maneira de remover uma chave de um documento ? ou seja, não apenas definir o valor como nulo, mas removê-lo?

User.findOne({}, function(err, user){
  //correctly sets the key to null... but it's still present in the document
  user.key_to_delete = null;

  // doesn't seem to have any effect
  delete user.key_to_delete;

  user.save();
});
Daniel Beardsley
fonte
1
Achei que tinha encontrado, mas depois de alguns testes: provavelmente não. No entanto, isso tem uma boa discussão sobre o assunto. groups.google.com/group/mongoose-orm/browse_thread/thread/…
Stephen
LOL deixa pra lá, acho que essa foi a sua postagem!
Stephen de

Respostas:

168

Nas versões anteriores, você teria que remover o driver node-mongodb-native. Cada modelo possui um objeto de coleção que contém todos os métodos que o node-mongodb-native oferece. Portanto, você pode fazer a ação em questão desta forma:

User.collection.update({_id: user._id}, {$unset: {field: 1 }});

Desde a versão 2.0, você pode fazer:

User.update({_id: user._id}, {$unset: {field: 1 }}, callback);

E desde a versão 2.4, se você já tem uma instância de um modelo, você pode fazer:

doc.field = undefined;
doc.save(callback);
staackuser2
fonte
Isso foi corrigido no Mongoose 2.X, portanto, você pode deixar a coleção de fora.
staackuser2
4
Use User.update({ _id: id }, { $unset: { field: 1 }}, callback)ou se você tiver uma instância de documento, defina o caminho como indefinido e salve-o:doc.field = undefined; doc.save()
aaronheckmann
25
Apenas uma observação que se você está tentando remover uma propriedade antiga que não está mais definida em seu esquema, você precisa fazerdoc.set('field', undefined)
evilcelery
3
que tal deletar doc.field.foo?
chovy de
28
@evilcelery doc.set('field', undefined)pode não ser suficiente, pois o modo estrito (padrão) não permite definir campos que não estão mais no esquema. doc.set('field', undefined, { strict: false })funcionou bem.
Alexander Link
56

Você vai querer fazer isso:

User.findOne({}, function(err, user){
  user.key_to_delete = undefined;
  user.save();
});
escrituras
fonte
3
Isso apenas o definirá como nulo - não o que o OP está pedindo.
Ian Henry
25
A partir da versão 2.4.0, definir uma chave de documento como indefinida passará o $ unset para mongodb aaronheckmann.posterous.com/mongoose-240
James Moore
30

Eu uso o mangusto e usar qualquer uma das funções acima atendeu ao requisito. A função compila sem erros, mas o campo ainda permaneceria.

user.set('key_to_delete', undefined, {strict: false} );

fez o truque para mim.

Noushad
fonte
Votar positivamente nesta resposta útil, pena que @ alexander-link não a tornou uma resposta em 2015 ( stackoverflow.com/questions/4486926/… )
w00t
1
Obrigado pela sua resposta, para mim, as outras soluções não funcionaram para objetos aninhados em matrizes!
BenSower,
@BenSower Este foi o meu caso também. Só esta solução funcionou bem porque eu tive que deletar um campo com array após encontrar o id de um documento específico
Luis Febro
Observe que a string é um caminho para a chave. Portanto, se o objeto que você deseja excluir está aninhado, você deve criar um caminho para ele. Essa resposta resolveu meu problema!
Bradyo,
8

Na sintaxe do mongo, para excluir alguma chave, você precisa fazer o seguinte:

{ $unset : { field : 1} }

Parece o mesmo em Mongoose.

Editar

Veja este exemplo.

Andrew Orsich
fonte
Você pode esclarecer esta resposta e dar um exemplo de código que se relacione com o código de exemplo acima?
Daniel Beardsley
desculpe, mas eu não estou experiente em mangusto. A sintaxe acima é a sintaxe mongo, então suponho que o driver de qualquer idioma suporte isso. Encontrei algum exemplo, verifique na minha resposta.
Andrew Orsich
1

Pode ser um problema colateral como usar

function (user)

ao invés de

function(err, user)

para o retorno de chamada do achado? Só estou tentando ajudar, pois já tinha o caso.

Luc
fonte
1

O documento Mongoose NÃO é um objeto javascript simples e é por isso que você não pode usar o operador delete (ou unsetda biblioteca 'lodash').

Suas opções são definir doc.path = null || undefined ou para usar o método Document.toObject () para transformar o documento mongoose em um objeto simples e, a partir daí, usá-lo normalmente. Leia mais em mongoose api-ref: http://mongoosejs.com/docs/api.html#document_Document-toObject

O exemplo seria mais ou menos assim:

User.findById(id, function(err, user) {
    if (err) return next(err);
    let userObject = user.toObject();
    // userObject is plain object
});
petarr
fonte
1

Experimentar:

User.findOne({}, function(err, user){
  // user.key_to_delete = null; X
  `user.key_to_delete = undefined;`

  delete user.key_to_delete;

  user.save();
});
Jeisson Valderrama
fonte
0

o problema com todas essas respostas é que elas funcionam para um campo. por exemplo, digamos que eu queira excluir todos os campos do meu documento se eles fossem uma string vazia "". Primeiro você deve verificar se o campo é uma string vazia e colocá-lo em $unset:

function unsetEmptyFields(updateData) {
  const $unset = {};
  Object.keys(updatedData).forEach((key) => {
    if (!updatedData[key]) {
      $unset[key] = 1;
      delete updatedData[key];
    }
  });
  updatedData.$unset = $unset;

  if (isEmpty(updatedData.$unset)) { delete updatedData.$unset; }

  return updatedData;
}

function updateUserModel(data){
const updatedData = UnsetEmptyFiled(data);

    const Id = "";
    User.findOneAndUpdate(
      { _id: Id },
      updatedData, { new: true },
    );
}
Milad Ranjbar
fonte
0

se você deseja remover uma chave da coleção, tente este método. isso funcionou para mim

 db.getCollection('myDatabaseTestCollectionName').update({"FieldToDelete": {$exists: true}}, {$unset:{"FieldToDelete":1}}, false, true);
Bivin Vinod
fonte
-4

você pode usar delete user._doc.key

Joel Esperanza
fonte