简体   繁体   English

如何在 mongoose 中更新数组中的嵌入文档,其中操作应该是原子的,应该更新最新的文档并返回更新的文档?

[英]How to update embedded document in array in mongoose where operation should be atomic, should update on the latest one and return updated document?

Currently working on node.js and MongoDB with mongoose.目前正在使用 mongoose 开发 node.js 和 MongoDB。

//Document in mongoDB
{
  name: 'first',
  _id: '1000'
  phases: [{
      _id: 1,
      phaseName: 'phase1',
      stories: [{
          _id: s1,
          sname: 'sfirst'
        },
        {
          _id: s2,
          sname: 'ssecond'
        },
        {
          _id: s3,
          sname: 'sthird'
        }
      ],

    },
    {
      _id: 2,
      phaseName: 'phase2',
      stories: [{
          _id: s1,
          sname: 'sfirst'
        },
        {
          _id: s2,
          sname: 'ssecond'
        },
        {
          _id: s3,
          sname: 'sthird'
        }
      ],

    }
  ],
}

All I have is我所拥有的是

  1. id=1000 (to find this document in mongodb) id=1000(在mongodb中找到这个文档)
  2. phaseId=1 and remstoryId=s2 (ie delete s2 from stories from phase with id 1) phaseId=1 和 remstoryId=s2(即从 id 为 1 的阶段的故事中删除 s2)
  3. phaseId=2, storyId={ _id: s4, sname: fourth}, position: 1 (add story in stories at index 1 in phase 2) phaseId=2, storyId={ _id: s4, sname: second}, position: 1 (在阶段2中索引1处的故事中添加故事)

Main requirement is this operation should be主要要求是这个操作应该是

  1. Atomic原子
  2. No other user can perform operation on this same document while performing above operation.执行上述操作时,其他用户无法对同一文档进行操作。 I mean lock this document.我的意思是锁定这个文件。

I can we can do this operation using findOne() and save()我可以使用 findOne() 和 save() 执行此操作吗

Model.findOne({
  id
}, (err, plan) => {
  if (!err) {

    //REMOVE THE STORY FROM PHASE
    const phase = plan.phases.find((phase) => phase._id === delPhaseID);
    phase.stories = phase.stories.filter((story) => story._id !== delStoryId);

    //ADD STORY IN STORIES
    const addPhase = plan.phases.find((phase) => phase._id === addPhaseID);
    addPhase.stories.splice(pos, 0, story);

    //SAVE PLAN
    plan.save((err, doc) => {
       if(!err)
         console.log(doc) // UPDATED DOCUMENT
       });
  }
})

but this operation is not atomic as per below image taken from masteringjs .但是这个操作不是原子操作,如下图来自masteringjs How can we solve this problem我们如何解决这个问题

在此处输入图片说明

You can try findOneAndUpdate() with arrayFilters ,你可以尝试findOneAndUpdate()arrayFilters

  • $pull to remove in p1 id's stories is s1p1 id 的故事中移除的$pulls1
  • $push to specific position for p2 use $position $pushp2特定位置使用$position
  • new: true to return updated document new: true返回更新的文档
Model.findOneAndUpdate(
    { _id: "1000" },
    {
        $pull: {
            "phases.$[p1].stories": {
                _id: "s1"
            }
        },
        $push: {
            "phases.$[p2].stories": {
                $each: [{
                    _id: "s4",
                    sname: "fourth"
                }],
                $position: 1
            }
        }
    },
    {
        arrayFilters: [
            { "p1._id": 1 },
            { "p2._id": 2 }
        ],
        new: true
    }
)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM