Como você transforma um documento do Mongoose em um objeto simples?

200

Eu tenho um documento de um mangusto que quero estender antes da codificação JSON e enviar como resposta. Se eu tentar adicionar propriedades ao documento, ele será ignorado. As propriedades não aparecem, Object.getOwnPropertyNames(doc)tornando impossível uma extensão normal. O estranho é que JSON.parse(JSON.encode(doc))funciona e retorna um objeto com todas as propriedades corretas. Existe uma maneira melhor de fazer isso?

respectTheCode
fonte

Respostas:

292

Mangusto Models herda de Documents, que possuem um toObject()método Acredito que o que você está procurando deve ser o resultado doc.toObject().

http://mongoosejs.com/docs/api.html#document_Document-toObject

jmar777
fonte
1
finalmente entendi. para aqueles que precisam de Objeto indefinido, certifique-se de chamar o documento em vez do modelo. exemplo: modelName._doc.toObject ()
John
1
Isso é bom, mas o lean () é o preferido.
Jason Sebring
Isso funciona se você retornar a matriz no Model.find({})retorno de documentos é uma matriz. Você pode docs.toObject?
tomada em branco
5
@jackblank se você tem uma variedade de modelos, então você deve ser capaz de mapear sobre eles:var docArray = modelArray.map(function(model) { return model.toObject(); });
jmar777
@ jmar777 Acho que a sua sugestão pertence como uma edição desta resposta.
R3wt
200

Outra maneira de fazer isso é informar ao Mongoose que tudo o que você precisa é de uma versão JavaScript simples do documento retornado usando lean()a cadeia de consulta. Dessa forma, o Mongoose ignora a etapa de criação da instância completa do modelo e você obtém diretamente uma docmodificação:

MyModel.findOne().lean().exec(function(err, doc) {
    doc.addedProperty = 'foobar';
    res.json(doc);
});
JohnnyHK
fonte
16
O uso da @Startec leangeralmente é mais eficiente porque você ignora a sobrecarga da criação do documento completo do Mongoose.
JohnnyHK 4/15
3
você é um campeão :) me corrija se eu estiver errado, mas você deve sempre se basear () nos seus achados () se não pretende modificar e salvar o documento que acabou de receber (digamos, se você está apenas tentando acessar o doc e enviá-lo de volta para o seu cliente)
Amarsh
1
@ Marsh Sim, embora isso também suponha que você não precise de nenhum dos métodos de instância ou virtuais definidos no esquema.
JohnnyHK
1
bizzare embora ... isso poderia ter sido uma opção com find () ... muitas vezes é muito comum ler um documento de um mongodb e enviá-lo de volta para um navegador da web. Gostaria de saber se find (). lean () realmente significa find () primeiro e, em seguida, aplique um lean () de cada elemento no resultado; nesse caso, a combinação find (). lean () seria realmente mais lenta que find () em si.
Amarsh
4
@Amarsh Não, o encadeamento lean()da consulta define a opção antes que a consulta seja realmente executada (por exec) para que os resultados estejam diretamente em sua forma "enxuta". Veja esta pergunta para ver o lado positivo do impacto no desempenho da chamada lean.
JohnnyHK
29

o caminho mais rápido se a propriedade não estiver no modelo:

document.set( key,value, { strict: false });

Alban Maillere
fonte
5
sim ... e por mais surpreendente que pareça, ainda acho que isso pode ser útil. Por exemplo, você mantém todas as primitivas do seu objeto.
maillere Alban
Obrigado por esta resposta, era o que eu estava procurando :) #
10789 datUser
6

Uma maneira melhor de resolver um problema como esse é usando doc.toObject()esse

doc.toObject({ getters: true })

outras opções incluem:

  • getters: aplicar todos os getters (caminho e getters virtuais)
  • virtuals: aplicar getters virtuais (pode substituir a opção getters)
  • minimize: remover objetos vazios (o padrão é true)
  • transform: uma função de transformação a ser aplicada ao documento resultante antes de retornar
  • depopulate: despovoar todos os caminhos preenchidos, substituindo-os por suas referências originais (o padrão é false)
  • versionKey: se deve incluir a chave da versão (o padrão é true)

então, por exemplo, você pode dizer

Model.findOne().exec((err, doc) => {
   if (!err) {
      doc.toObject({ getters: true })
      console.log('doc _id:', doc._id)
   }
})

e agora vai funcionar.

Para referência, consulte: http://mongoosejs.com/docs/api.html#document_Document-toObject

Jalasem
fonte
3

Para obter um objeto simples do documento Mongoose, usei a _docpropriedade da seguinte maneira

mongooseDoc._doc  //returns plain json object

Eu tentei com toObjectmas me deu funções, argumentos e todas as outras coisas que eu não preciso.

dd619
fonte
3
Acessar propriedades ou métodos com _no início não é a solução ideal. Usar o lean pode resolver seu caso.
Arthur Costa
@ArthurBrito yes. Não é uma solução ideal, mas ainda é uma SOLUÇÃO! . Não há necessidade de voto negativo. Eu usei _docpropriedade muitas vezes sem enfrentar nenhum problema. E usar o leanmétodo fornece um objeto simples no qual você não pode executar operações do modelo mangusto.
Dd619
você está certo. Basta adicionar em sua resposta que não é a solução ideal, então eu vou remover o downvote (I não pode remover a menos que você editado)
Arthur Costa
2

Você também pode especificar o objeto e, em seguida, analisar novamente para criar o objeto normal. Por exemplo, como: -

const obj = JSON.parse(JSON.stringify(mongoObj))
kaushik_pm
fonte