Object.assign()在分配mongoose doc时创建了wierd属性

时间:2018-01-03 20:28:12

标签: node.js mongoose assign

MessageThread.findById(req.body._id)
      .populate({ path: "messages" })
      .exec((err, foundMessageThread) => {
        var filtered = foundMessageThread.messages.map(message=>{
          return Object.assign({}, message, {isRead: true});
        })
        console.log("filtered", filtered);

      });

console.log显示:

{ '$__':
 InternalCache {
   strictMode: true,
   selected: {},
   shardval: undefined,
   saveError: undefined,
   validationError: undefined,
   adhocPaths: undefined,
   removing: undefined,
   inserting: undefined,
   version: undefined,
   getters: {},
   _id: 5a4c7f2d8b49fc260c396f55,
   populate: undefined,
   populated: undefined,
   wasPopulated: true,
   scope: undefined,
   activePaths: [Object],
   pathsToScopes: {},
   ownerDocument: undefined,
   fullPath: undefined,
   emitter: [Object],
   '$options': true },
isNew: false,
errors: undefined,
_doc:
 { sentAt: 2018-01-03T06:58:53.188Z,
   isRead: false,
   _id: 5a4c7f2d8b49fc260c396f55,
   sender: 5a4b77767251b44cd870219f,
   reciever: 5a4b780a7251b44cd87021a1,
   text: 'qwe',
   __v: 0 },
'$init': true,
isRead: true },
......

它重复了很多次。 我想它(InternalCache {strictMode:true ...)与消息相关,取自 foundMessageThread 。并且它在分配时显示其元数据(在我的术语中)。这是因为:

MessageThread.findById(req.body._id)
  .populate({ path: "messages" })
  .exec((err, foundMessageThread) => {
    var filtered = foundMessageThread.messages.map(message=>{
      console.log("message", message)
      return Object.assign({}, message, {isRead: true});
    })
    console.log("filtered", filtered);

  });

console.log显示

{ sentAt: 2018-01-03T06:58:53.188Z,
  isRead: false,
  _id: 5a4c7f2d8b49fc260c396f55,
  sender: 5a4b77767251b44cd870219f,
  reciever: 5a4b780a7251b44cd87021a1,
  text: 'qwe',
  __v: 0 },
....

我的问题:

  1. 这是正常行为吗?
  2. 如果是如何解决的?因为"元数据"防止分配对象。
  3. P.S。我试过了:

    MessageThread.findById(req.body._id)
      .populate({ path: "messages" })
      .exec((err, foundMessageThread) => {
        var filtered = foundMessageThread.messages.map(message=>{
          return **Object.assign({}, message._doc, {isRead: true})**;
        })
        console.log("filtered", filtered);
    
      });
    

3 个答案:

答案 0 :(得分:7)

这是猫鼬的正常行为。由mongoose返回的对象包装实际数据,以便向其添加行为(方法)。

您可以使用toObject方法访问实际数据对象,例如message.toObject()

然而,像__v这样的属性被猫鼬用于管家。如果您不想要它们,可以像这样修改toObject方法

messageSchema.set('toObject', {
  versionKey: false,
  transform: (doc, ret) => {
    delete ret.__v;
    return ret;
  },
});

答案 1 :(得分:1)

似乎要引用猫鼬对象的_doc属性,如果要分配给这些对象或从这些对象分配。实际上,我无法像mongoDoc.newProp = propValue;那样以常规方式设置其他属性。它并没有改变原始对象。

要分配,而不是:

Object.assign(mongoDoc, {a: 1, b: 2});

您想要:

Object.assign(mongoDoc._doc, {a: 1, b: 2});

或者如果您要将mongoDoc属性分配给另一个对象,则需要

Object.assign({a: 1, b: 2}, mongoDoc._doc);

答案 2 :(得分:1)

您还可以对猫鼬请求使用.lean()方法。这样可以减少麻烦的响应并轻松处理它:

try {
    const assets = await myModel.Assets
      .find({ isActive: true }, { __v: 0, _id: 0 })
      .lean()
      .exec()
    // do something
}
catch(error) {
  throw error
}