Как вы превращаете документ Mongoose в простой объект?

200

У меня есть документ от мангуста, который я хочу расширить до кодирования JSON и отправки в ответ. Если я пытаюсь добавить свойства в документ, он игнорируется. Свойства не отображаются в Object.getOwnPropertyNames(doc)нормальном расширении невозможно. Странно то, что JSON.parse(JSON.encode(doc))работает и возвращает объект со всеми правильными свойствами. Есть лучший способ сделать это?

respectTheCode
источник

Ответы:

292

Мангусты Models наследуются от Documents, у которых есть toObject()метод. Я считаю, что то, что вы ищете, должно быть результатом doc.toObject().

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

jmar777
источник
1
наконец получил это. для тех, у кого toObject не определено, обязательно вызовите документ вместо модели. то есть modelName._doc.toObject ()
Джон
1
Это нормально, но lean () предпочтительнее.
Джейсон Себринг,
Работает ли это, если вы возвращаете массив Model.find({})в документах, возвращаемый массив. Вы можете docs.toObject?
Джек
5
@jackblank Если у вас есть массив Моделей, вы сможете отобразить их:var docArray = modelArray.map(function(model) { return model.toObject(); });
jmar777
@ jmar777 Я думаю, что ваше предложение относится к редактированию этого ответа.
r3wt
201

Еще один способ сделать это - сообщить Mongoose, что все, что вам нужно, - это простая версия JavaScript возвращаемого документа с помощью lean()цепочки запросов. Таким образом, Mongoose пропускает этап создания экземпляра полной модели, и вы сразу получаете, docчто можете изменить:

MyModel.findOne().lean().exec(function(err, doc) {
    doc.addedProperty = 'foobar';
    res.json(doc);
});
JohnnyHK
источник
17
@Startec Использование, leanкак правило, более производительно, потому что вы пропускаете накладные расходы на первое создание полного документа Mongoose.
JohnnyHK
3
Вы чемпион :) поправьте меня, если я ошибаюсь, но вы всегда должны опираться () на свои find (), если вы не собираетесь изменять и сохранять только что полученный документ (скажем, если вы просто пытаетесь получить доступ к документ и отправьте его обратно вашему клиенту)
Amarsh
1
@Amarsh Да, хотя это также предполагает, что вам не нужны какие-либо методы экземпляров или виртуальные объекты, определенные в схеме.
JohnnyHK
1
bizzare, хотя ... это могло быть вариантом с find () ... часто слишком часто, чтобы читать документ из mongodb и отправлять его обратно в веб-браузер. Интересно, если find (). lean () на самом деле означает сначала find (), а затем применяет lean () каждого элемента в результате, в этом случае комбинация find (). lean () будет на самом деле медленнее, чем find () сам.
Amarsh
4
@ Amarsh Нет, цепочка lean()запроса устанавливает опцию до того, как запрос будет фактически выполнен ( exec), чтобы результаты были непосредственно в их «худой» форме. Посмотрите этот вопрос, чтобы узнать о положительном влиянии на производительность lean.
JohnnyHK
29

быстрый способ, если свойство не в модели:

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

Alban Maillere
источник
5
да ... и как это ни удивительно, я все еще думаю, что это может быть полезно. Например, вы сохраняете все примитивы вашего объекта.
Албан Мэйллер
Спасибо за этот ответ, это было то, что я искал :)
datUser
6

Лучший способ решения такой проблемы - использовать doc.toObject()вот так

doc.toObject({ getters: true })

другие варианты включают в себя:

  • getters: применить все методы получения (пути и виртуальные методы получения)
  • virtuals: применять виртуальные геттеры (можно переопределить опцию геттеров)
  • minimize: удалить пустые объекты (по умолчанию true)
  • transform: функция преобразования, применяемая к полученному документу перед возвратом
  • depopulate: удалить все заполненные пути, заменив их исходными ссылками (по умолчанию false)
  • versionKey: включать ли ключ версии (по умолчанию true)

так, например, вы можете сказать,

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

и теперь это будет работать.

Для справки см .: http://mongoosejs.com/docs/api.html#document_Document-toObject

Jalasem
источник
3

Чтобы получить простой объект из документа Mongoose, я использовал _docсвойство следующим образом

mongooseDoc._doc  //returns plain json object

Я пытался, toObjectно это дало мне функции, аргументы и все остальное, что мне не нужно.

dd619
источник
3
Доступ к свойствам или методам с _самого начала - не идеальное решение. Использование постного может решить ваш случай.
Артур Коста
@ArthurBrito да. Это не идеальное решение, но все еще РЕШЕНИЕ! , Не нужно занижать ответ. Я использовал _docсобственность много раз, не сталкиваясь ни с какой проблемой. И использование leanметода дает вам простой объект, на котором вы не можете выполнять операции модели мангуста.
дд 619
ты прав. Просто добавьте в свой ответ, что это не идеальное решение, тогда я уберу понижающее голосование (я не могу удалить, если вы не отредактировали)
Артур Коста
2

Вы также можете привести в порядок объект, а затем снова проанализировать, чтобы сделать нормальный объект. Например, как: -

const obj = JSON.parse(JSON.stringify(mongoObj))
kaushik_pm
источник