Mongooseドキュメントをプレーンオブジェクトにするにはどうすればよいですか?


200

JSONエンコーディングの前に拡張して応答として送信したいというマングースのドキュメントがあります。プロパティをドキュメントに追加しようとしても無視されます。プロパティはObject.getOwnPropertyNames(doc)、通常の拡張を不可能にすると表示されません。奇妙なことにJSON.parse(JSON.encode(doc))、すべての正しいプロパティを持つオブジェクトが機能して返されます。これを行うより良い方法はありますか?

回答:


292

Mongoose は、メソッドを持つModelから継承します。あなたが探しているのはの結果だと思います。DocumenttoObject()doc.toObject()

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


1
ついに手に入れました。toObjectが未定義の場合は、モデルではなくドキュメントを呼び出すようにしてください。ie modelName._doc.toObject()
John

1
これは問題ありませんが、lean()が推奨されます。
Jason Sebring 2016年

Model.find({})ドキュメントで配列を返す場合、これは機能しますか?docs.toObjectを使用できますか?
ジャックブランク

5
@jackblankあなたがモデルの配列を持っている場合、あなたはそれらの上にマッピングすることができる必要があります:var docArray = modelArray.map(function(model) { return model.toObject(); });
jmar777

@ jmar777私はあなたの提案がこの回答の編集として属していると思います。
r3wt

200

これを行う別の方法lean()は、クエリチェーンで使用することにより、返されるドキュメントのプレーンなJavaScriptバージョンのみが必要であることをMongooseに伝えることです。そうすることで、Mongooseは完全なモデルインスタンスを作成するステップをスキップし、直接doc変更できるようになります。

MyModel.findOne().lean().exec(function(err, doc) {
    doc.addedProperty = 'foobar';
    res.json(doc);
});

16
@Startecを使用するleanと、最初に完全なMongooseドキュメントを作成するオーバーヘッドをスキップできるため、一般的にパフォーマンスが向上します。
JohnnyHK、2015年

3
あなたはチャンピオンです:)私が間違っている場合は私を修正してください。ただし、受け取ったばかりのドキュメントを変更して保存するつもりがない場合(たとえば、文書化してクライアントに
送り返す

1
@Amarshはい。ただし、スキーマで定義されているインスタンスメソッドや仮想変数が必要ないことも前提としています。
JohnnyHK 2015年

1
bizzareしかし...これはfind()のオプションである可能性があります... mongodbからドキュメントを読み取り、それをWebブラウザーに送信することはあまりにも一般的です。find()。lean()が実際に最初にfind()を意味し、次に結果の各要素のlean()を適用するかどうか疑問に思います。この場合、find()。lean()の組み合わせは実際にはfind()よりも遅くなります。自体。
アマーシュ2015年

4
@Amarshいいえ、lean()クエリをチェーンすると、クエリが実際に(によってexec)実行される前にオプションが設定されるため、結果は直接「リーン」形式になります。呼び出しによるパフォーマンスへのプラスの影響については、この質問を参照してくださいlean
JohnnyHK、2015年

29

プロパティがモデルにない場合の高速な方法:

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


5
はい...そして、見た目と同じくらい驚くべきことですが、これはまだ役に立つと思います。たとえば、オブジェクトのすべてのプリミティブを保持します。
alban maillere 2014年

この答えをありがとう、それは私が探していたものでした:)
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を参照してください。


3

Mongooseドキュメントからプレーンオブジェクトを取得するには_doc、次のようにプロパティを使用しました

mongooseDoc._doc  //returns plain json object

私は試しましたtoObjectが、それは私に必要のない関数、引数、および他のすべてのものを与えました。


3
_最初からプロパティまたはメソッドにアクセスする ことは、理想的なソリューションではありません。リーンを使用すると、ケースが解決する場合があります。
Arthur Costa

@ArthurBritoはい。それは理想的なソリューションではありませんが、それでも解決策です!。回答に反対票を投じる必要はありません。私は_doc何の問題もなく何回も財産を使いました。また、leanメソッドを使用すると、マングースモデルの操作を実行できないプレーンオブジェクトが得られます。
dd619

あなたが正しい。理想的な解決策ではない回答を追加するだけで、反対票を削除します(編集しない限り削除できません)
Arthur Costa

2

オブジェクトを文字列化し、再度解析して通常のオブジェクトを作成することもできます。たとえば、次のようになります。

const obj = JSON.parse(JSON.stringify(mongoObj))
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.