Node.js 在mongoose结果上使用lodash cloneDeep()-can';t更新生成的JSON

Node.js 在mongoose结果上使用lodash cloneDeep()-can';t更新生成的JSON,node.js,express,mongoose,lodash,Node.js,Express,Mongoose,Lodash,正在使用的技术:Node.js、Express、Mongoose、Mocha、lodash 在测试我的服务时,我的应用程序: 获取使用Mongoose保存新文档的结果 使用lodash.cloneDeep()克隆结果 尝试更改克隆实例的内容 结果是我得到了一个处于非常奇怪状态的克隆文档。在尝试修改值时,如果查询已更改的特定对象的值,它将显示正确的值。然而,当我只是将文档本身转储到控制台时,就好像我没有更新值一样。同样,如果我将文档传递到save例程,它会将文档保存到MongoDb,就好像我没有更

正在使用的技术:Node.js、Express、Mongoose、Mocha、lodash

在测试我的服务时,我的应用程序:

  • 获取使用Mongoose保存新文档的结果
  • 使用lodash.cloneDeep()克隆结果
  • 尝试更改克隆实例的内容
  • 结果是我得到了一个处于非常奇怪状态的克隆文档。在尝试修改值时,如果查询已更改的特定对象的值,它将显示正确的值。然而,当我只是将文档本身转储到控制台时,就好像我没有更新值一样。同样,如果我将文档传递到save例程,它会将文档保存到MongoDb,就好像我没有更改任何值一样

    代码如下:

    测试代码:

    describe('### UPDATE ALARM', function () {
        it('Should save an alarm record for newly created asset', async () => {
            var asset = await Asset.findOne({ _id: compAdminAsset })
            const req = { user: { _id: compAdminId } }
            var alarm = await AlarmController.getByAsset(req, asset)
            expect(alarm._user).to.be.equal(compAdminId)
            expect(alarm._asset).to.be.equal(compAdminAsset)
    
            var newAlarm = _.cloneDeep(alarm)
            console.log('#### Newly Cloned Alarm Object')
            console.log(newAlarm)
    
            // change the rhSettings values
            newAlarm.rhSettings.rhAlarmLow = true
            newAlarm.rhSettings.rhAlarmHigh = true
            newAlarm.rhSettings.rhLow = 40
            newAlarm.rhSettings.rhHigh = 85
    
            console.log()
            console.log('#### Cloned Alarm Object AFTER updating values')
            console.log(newAlarm)
    
            console.log()
            console.log('####  Directly query the values that were changed ')
            console.log('newAlarm.rhSettings.rhAlarmLow: ' + newAlarm.rhSettings.rhAlarmLow)
            console.log('newAlarm.rhSettings.rhAlarmHigh: ' + newAlarm.rhSettings.rhAlarmHigh)
            console.log('newAlarm.rhSettings.rhLow: ' + newAlarm.rhSettings.rhLow)
            console.log('newAlarm.rhSettings.rhLow:  '+ newAlarm.rhSettings.rhHigh)
    
            var savedAlarm = await AlarmController.update(req, newAlarm)
            .
            .
            .
        })
    })
    
    测试代码的输出:

        ### UPDATE ALARM
    #### Newly Cloned Alarm Object
    { rhSettings:
       { rhLow: 0, rhHigh: 80, rhAlarmLow: false, rhAlarmHigh: false },
      tempSettings:
       { tempLow: 50,
         tempHigh: 100,
         tempAlarmLow: false,
         tempAlarmHigh: false },
      _user: 'c86a7618-2323-48ec-b9e0-0d953301e37f',
      _asset: '6ca7a1ba-fc16-4cbf-9b4d-029c508d6b6c',
      _id: 5bde26a5038bec31683b8d80,
      createdAt: 2018-11-03T22:52:21.604Z,
      updatedAt: 2018-11-03T22:52:21.604Z,
      __v: 0 }
    
    #### Cloned Alarm Object AFTER updating values
    { rhSettings:
       { rhLow: 0, rhHigh: 80, rhAlarmLow: false, rhAlarmHigh: false },
      tempSettings:
       { tempLow: 50,
         tempHigh: 100,
         tempAlarmLow: false,
         tempAlarmHigh: false },
      _user: 'c86a7618-2323-48ec-b9e0-0d953301e37f',
      _asset: '6ca7a1ba-fc16-4cbf-9b4d-029c508d6b6c',
      _id: 5bde26a5038bec31683b8d80,
      createdAt: 2018-11-03T22:52:21.604Z,
      updatedAt: 2018-11-03T22:52:21.604Z,
      __v: 0 }
    
    #### Query the values that were changed directly
    newAlarm.rhSettings.rhAlarmLow: true
    newAlarm.rhSettings.rhAlarmHigh: true
    newAlarm.rhSettings.rhLow: 40
    newAlarm.rhSettings.rhLow:  85
    
    返回“newAlarm”对象的代码:


    知道是什么导致克隆的JSON对象处于这种奇怪的状态吗?

    为了让mongoose对更改跟踪等感到满意而使用的方法

    然而,我非常怀疑克隆对象和使用set是否会是一种接近最佳实践的做法

    为什么不简单地创建另一个模型?为什么要通过克隆来规避猫鼬中的内置更改跟踪等

    你不妨简单地使用你的新猫鼬模型。。。跳过克隆。。。更改值等。。。然后,只需将该对象传递给
    新模型(yourObjectWithChanges)
    ,然后保存:

    var newAlarm = alarm.toObject() 
    ... do your changes
    let newAlarmModel = new Model(newAlarm)
    await newAlarmModel.save()
    

    谢谢@Akrion!我删除了lodash cloneDeep()并直接将newAlarm实例化为一个新的模式实例(newAlarm=newAlarm(Alarm)),现在它工作得很好。我甚至不需要闹钟。toObject()行。
    var newAlarm = alarm.toObject() 
    ... do your changes
    let newAlarmModel = new Model(newAlarm)
    await newAlarmModel.save()