Làm thế nào để bạn biến một tài liệu Mongoose thành một đối tượng đơn giản?


200

Tôi có một tài liệu từ một cầy mangut mà tôi muốn gia hạn trước khi mã hóa JSON và gửi đi dưới dạng phản hồi. Nếu tôi thử thêm thuộc tính vào tài liệu thì nó bị bỏ qua. Các thuộc tính không xuất hiện trong Object.getOwnPropertyNames(doc)việc mở rộng bình thường là không thể. Điều kỳ lạ là nó JSON.parse(JSON.encode(doc))hoạt động và trả về một đối tượng với tất cả các thuộc tính chính xác. Có cách nào tốt hơn để làm điều này?

Câu trả lời:


292

Mongoose Models thừa kế từ Documents, có một toObject()phương thức. Tôi tin rằng những gì bạn đang tìm kiếm nên là kết quả của doc.toObject().

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


1
cuối cùng cũng hiểu. đối với những người có toObject không xác định, hãy đảm bảo gọi trên tài liệu thay vì mô hình. tức là modelName._doc.toObject ()
John

1
Điều này là OK nhưng lean () được ưa thích.
Jason Sebring

Điều này có hoạt động không nếu bạn trả về mảng trên Model.find({})tài liệu trả về là một mảng. Bạn có thể docs.toObject?
jack trống

5
@jackblank nếu bạn có một loạt Mô hình, thì bạn sẽ có thể ánh xạ qua chúng:var docArray = modelArray.map(function(model) { return model.toObject(); });
jmar777

@ jmar777 tôi nghĩ đề xuất của bạn thuộc về chỉnh sửa câu trả lời này.
r3wt

200

Một cách khác để làm điều này là nói với Mongoose rằng tất cả những gì bạn cần là một phiên bản JavaScript đơn giản của tài liệu được trả về bằng cách sử dụng lean()trong chuỗi truy vấn. Bằng cách đó, Mongoose bỏ qua bước tạo cá thể mô hình đầy đủ và bạn trực tiếp nhận được một thứ docbạn có thể sửa đổi:

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

16
@Startec Sử dụng leanthường hiệu quả hơn vì bạn bỏ qua chi phí đầu tiên tạo tài liệu Mongoose đầy đủ.
JohnnyHK

3
bạn là một nhà vô địch :) hãy sửa lỗi cho tôi nếu tôi sai, nhưng bạn nên luôn luôn nghiêng () bạn tìm () nếu bạn không có ý định sửa đổi và lưu tài liệu bạn vừa nhận được (giả sử, nếu bạn chỉ đang cố gắng truy cập vào doc và gửi lại cho khách hàng của bạn)
Amarsh

1
@Amarsh Có, mặc dù điều đó cũng cho rằng bạn không cần bất kỳ phương thức cá thể hoặc ảo nào được xác định trong lược đồ.
JohnnyHK

1
bizzare mặc dù ... đây có thể là một tùy chọn với find () ... việc đọc tài liệu từ mongodb và gửi lại cho trình duyệt web thường là quá phổ biến. Tôi tự hỏi nếu find (). lean () thực sự có nghĩa là find () trước và sau đó áp dụng lean () của mỗi phần tử trong kết quả, trong trường hợp đó, kết hợp find (). lean () thực sự sẽ chậm hơn find () chinh no.
Amarsh

4
@Amarsh Không, xâu chuỗi lean()truy vấn sẽ đặt tùy chọn trước khi truy vấn thực sự được thực thi (bởi exec) để các kết quả được trực tiếp ở dạng "nạc" của chúng. Xem câu hỏi này cho mặt tác động tích cực của cuộc gọi lean.
JohnnyHK

29

cách nhanh chóng nếu tài sản không có trong mô hình:

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


5
vâng ... và đáng ngạc nhiên như nó có thể nhìn, tôi vẫn nghĩ rằng điều này có thể hữu ích. Ví dụ, bạn giữ tất cả các nguyên thủy của đối tượng của bạn.
alban maillere

Cảm ơn câu trả lời này, đó là những gì tôi đang tìm kiếm :)
datUser 10/2/2015

6

Một cách tốt hơn để giải quyết một vấn đề như thế này là sử dụng doc.toObject()như thế này

doc.toObject({ getters: true })

các tùy chọn khác bao gồm:

  • getters: áp dụng tất cả các getters (đường dẫn và getters ảo)
  • virtuals: áp dụng getters ảo (có thể ghi đè tùy chọn getters)
  • minimize: xóa các đối tượng trống (mặc định là đúng)
  • transform: một hàm biến đổi để áp dụng cho tài liệu kết quả trước khi quay trở lại
  • depopulate: hủy bỏ bất kỳ đường dẫn dân cư nào, thay thế chúng bằng các giới thiệu ban đầu của chúng (mặc định là sai)
  • versionKey: có bao gồm khóa phiên bản hay không (mặc định là đúng)

vì vậy ví dụ bạn có thể nói

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

và bây giờ nó sẽ hoạt động.

Để tham khảo, xem: http://mongoosejs.com/docs/api.html#document_Document-toObject


3

Để có được đối tượng đơn giản từ tài liệu Mongoose, tôi đã sử dụng thuộc _doctính như sau

mongooseDoc._doc  //returns plain json object

Tôi đã thử với toObjectnhưng nó cho tôi chức năng, đối số và tất cả những thứ khác mà tôi không cần.


3
Truy cập các thuộc tính hoặc phương thức _ngay từ đầu, đây không phải là giải pháp lý tưởng. Sử dụng lean có thể giải quyết trường hợp của bạn.
Arthur Costa

@ArthurBrito có. Nó không phải là một giải pháp lý tưởng nhưng nó vẫn là GIẢI PHÁP! . Không cần downvote trả lời. Tôi đã sử dụng _doctài sản nhiều lần mà không gặp phải bất kỳ vấn đề. Và sử dụng leanphương thức cung cấp cho bạn đối tượng đơn giản mà bạn không thể thực hiện các hoạt động mô hình cầy mangut.
dd619

bạn đúng. Chỉ cần thêm vào câu trả lời của bạn không phải là giải pháp lý tưởng sau đó tôi sẽ xóa downvote (Tôi không thể xóa trừ khi bạn chỉnh sửa)
Arthur Costa

2

Bạn cũng có thể xâu chuỗi đối tượng và sau đó phân tích lại để tạo đối tượng bình thường. Ví dụ như: -

const obj = JSON.parse(JSON.stringify(mongoObj))
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.