【问题标题】:Object.assign() creates wierd properties when assigns mongoose docObject.assign() 在分配 mongoose 文档时创建奇怪的属性
【发布时间】:2018-06-13 13:22:28
【问题描述】:
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...) 与取自 foundMessageThreadmessage 相关。它在分配时会显示其元数据(在我的术语中)。因为:

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. 如果是怎么修复呢?因为“元数据”会阻止分配对象。

附:我试过了:

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);

  });

【问题讨论】:

    标签: node.js mongoose assign


    【解决方案1】:

    这是猫鼬的正常行为。 mongoose 返回的对象封装了实际的数据,从而为其添加行为(方法)。

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

    不过,也有像 __v 这样的属性,mongoose 使用这些属性来做家务。如果你不想要它们,你可以像这样修改toObject方法

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

    【讨论】:

    • 感谢@AkshendraPratap。但是为什么当我执行Object.assign() 时它会出现,而当我执行console.log() 时却没有。例如,在console.log("message") 上面的第三个代码中显示了常规文档。但是当我做Object.assign() 时,实际数据会弹出吗? ))
    • 在更高级别上,要将对象打印为字符串,console.log 将使用toString() 函数。 Mongoose 为其文档提供了一个toString 作为助手。这基本上是重新调整toObject。你可以看这里的代码,github.com/Automattic/mongoose/blob/…
    【解决方案2】:

    如果您想分配给这些对象或从这些对象分配,似乎应该引用猫鼬对象的_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);

    【讨论】:

    • 行得通,但对我来说这不是一个干净的方法!
    【解决方案3】:

    您也可以将.lean() 方法与猫鼬请求一起使用。这样可以减少繁琐的响应并轻松处理它:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-10-06
      • 2017-09-06
      • 1970-01-01
      • 2019-09-13
      相关资源
      最近更新 更多