คุณจะเปลี่ยนเอกสาร Mongoose เป็นวัตถุธรรมดาได้อย่างไร


200

ฉันมีเอกสารจากพังพอนพบว่าฉันต้องการขยายก่อนการเข้ารหัส JSON และส่งออกเป็นการตอบสนอง ถ้าฉันลองเพิ่มคุณสมบัติลงในเอกสารมันจะถูกละเว้น คุณสมบัติไม่ปรากฏในObject.getOwnPropertyNames(doc)การขยายเวลาปกติเป็นไปไม่ได้ สิ่งที่แปลกคือใช้JSON.parse(JSON.encode(doc))งานได้และส่งคืนวัตถุที่มีคุณสมบัติที่ถูกต้องทั้งหมด มีวิธีที่ดีกว่าในการทำเช่นนี้?

คำตอบ:


292

Mongoose Models สืบทอดมาจากDocuments ซึ่งมีtoObject()วิธีการ doc.toObject()ผมเชื่อว่าสิ่งที่คุณกำลังมองหาที่ควรจะเป็นผลมาจากการ

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


1
ในที่สุดก็ได้รับมัน สำหรับผู้ที่มีวัตถุไม่ได้กำหนดให้โทรบนเอกสารแทนรุ่น ie modelName._doc.toObject ()
John

1
นี่เป็นเรื่องปกติ แต่เป็นที่ต้องการน้อยกว่า ()
Jason Sebring

ใช้งานได้ไหมถ้าคุณส่งคืนอาร์เรย์ในModel.find({})การส่งคืนเอกสารเป็นอาร์เรย์ คุณสามารถ docs.toObject ได้ไหม
แจ็คว่างเปล่า

5
@jackblank ถ้าคุณมีนางแบบมากมายแล้วคุณควรจะแมปพวกมันได้:var docArray = modelArray.map(function(model) { return model.toObject(); });
jmar777

@ jmar777 ฉันคิดว่าคำแนะนำของคุณเป็นของการแก้ไขคำตอบนี้
r3wt

202

อีกวิธีในการทำเช่นนี้คือบอก Mongoose ว่าสิ่งที่คุณต้องมีก็คือเอกสาร JavaScript ที่ส่งคืนแบบธรรมดาโดยใช้lean()ในสายการสืบค้น วิธีที่พังพอนข้ามขั้นตอนของการสร้างอินสแตนซ์เต็มรูปแบบและคุณได้รับโดยตรงdocคุณสามารถปรับเปลี่ยน:

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

17
@Startec Using leanโดยทั่วไปแล้วจะมีประสิทธิภาพมากกว่าเพราะคุณข้ามค่าโสหุ้ยในการสร้างเอกสารพังพอนแบบเต็ม
JohnnyHK

3
คุณเป็นผู้ชนะเลิศ :) แก้ไขให้ฉันถ้าฉันผิด แต่คุณควรยัน () หา () ของคุณถ้าคุณไม่ต้องการแก้ไขและบันทึกเอกสารที่คุณเพิ่งได้รับ (พูดถ้าคุณแค่พยายามเข้าถึง เอกสารและส่งกลับไปยังลูกค้าของคุณ)
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 });


5
ใช่ ... และน่าประหลาดใจอย่างที่เห็นฉันยังคิดว่านี่อาจเป็นประโยชน์ได้ ตัวอย่างเช่นคุณเก็บดั้งเดิมของวัตถุทั้งหมดของคุณ
alban maillere

ขอบคุณสำหรับคำตอบนี้มันเป็นสิ่งที่ฉันกำลังมองหา :)
datUser

6

วิธีที่ดีกว่าในการแก้ปัญหาเช่นนี้คือใช้doc.toObject()สิ่งนี้

doc.toObject({ getters: true })

ตัวเลือกอื่น ๆ ได้แก่ :

  • getters: ใช้ getters ทั้งหมด (path และ virtual getters)
  • virtuals: ใช้ getters เสมือน (สามารถแทนที่ตัวเลือก getters)
  • minimize: ลบวัตถุที่ว่างเปล่า (ค่าเริ่มต้นเป็นจริง)
  • transform: ฟังก์ชั่นการแปลงเพื่อนำไปใช้กับเอกสารที่เป็นผลลัพธ์ก่อนส่งคืน
  • depopulate: depopulate เส้นทางที่มีประชากรแทนที่ด้วย refs เดิมของพวกเขา (ค่าเริ่มต้นเป็นเท็จ)
  • versionKey: ไม่ว่าจะรวมคีย์รุ่น (ค่าเริ่มต้นเป็นจริง)

ตัวอย่างเช่นคุณสามารถพูดได้

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

เพื่อรับวัตถุธรรมดาจากเอกสารพังพอนฉันใช้_docคุณสมบัติดังต่อไปนี้

mongooseDoc._doc  //returns plain json object

ฉันลองด้วยtoObjectแต่มันให้ฟังก์ชั่นการโต้แย้งและสิ่งอื่น ๆ ทั้งหมดที่ฉันไม่ต้องการ


3
การเข้าถึงคุณสมบัติหรือวิธีการด้วย _ในตอนแรกไม่ใช่วิธีที่ดีที่สุด การใช้ยันอาจแก้ปัญหากรณีของคุณ
Arthur Costa

@ArthurBrito ใช่ มันไม่ใช่ทางออกที่ดี แต่ยังคงเป็นโซลูชั่น! . ไม่จำเป็นต้องลงคะแนนคำตอบ ฉันเคยใช้_docอสังหาริมทรัพย์หลายครั้งโดยไม่ประสบปัญหาใด ๆ และleanวิธีการใช้ให้วัตถุธรรมดาที่คุณไม่สามารถดำเนินการรูปแบบพังพอน
dd619

คุณถูก. เพียงแค่เพิ่มคำตอบของคุณที่ไม่ใช่ทางออกที่ดีที่สุดแล้วฉันจะลบ downvote (ฉันไม่สามารถลบออกได้เว้นแต่คุณจะแก้ไข)
Arthur Costa

1

นอกจากนี้คุณยังสามารถทำให้วัตถุเป็นสตริงและแยกวิเคราะห์อีกครั้งเพื่อสร้างวัตถุปกติ ตัวอย่างเช่น: -

const obj = JSON.parse(JSON.stringify(mongoObj))
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.