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();
});

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);

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


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.


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.


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.


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
});

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();
});

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 },
    );
}

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);

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.