在同一文档MongoDB中将元素从一个数组移动到另一个数组

时间:2018-01-04 22:22:11

标签: arrays mongodb

我的数据如下:

{
  "_id": ObjectId("4d525ab2924f0000000022ad"),
  "array": [
    { id: 1, other: 23 },
    { id: 2, other: 21 },
    { id: 0, other: 235 },
    { id: 3, other: 765 }
  ],
  "zeroes": []
}

我想从一个数组中拉出一个元素并将$推送到同一文档中的第二个数组,以产生如下所示的内容:

{
  "_id": ObjectId("id"), 
  "array": [
    { id: 1, other: 23 },
    { id: 2, other: 21 },
    { id: 3, other: 765 }
  ],
  "zeroes": [
    { id: 0, other: 235 }
  ]
}

我意识到我可以通过执行查找然后更新来完成此操作,即

db.foo.findOne({"_id": param._id})
.then((doc)=>{
  db.foo.update(
    {
      "_id": param._id
    },
    {
      "$pull": {"array": {id: 0}},
      "$push": {"zeroes": {doc.array[2]} }
    }
  )
})

我想知道是否有原子功能,我可以用它来做。 像,

db.foo.update({"_id": param._id}, {"$move": [{"array": {id: 0}}, {"zeroes": 1}]}

发现这篇文章慷慨地提供了我使用的数据,但这个问题在4年后仍未解决。在过去的4年里,有没有一个解决方案?

Move elements from $pull to another array

1 个答案:

答案 0 :(得分:0)

There is no $move in MongoDB。话虽这么说,最简单的解决方案是两阶段方法:

  1. 查询文档
  2. 使用$pull$push / $addToSet
  3. 制作更新

    这里,确保一切都是幂等的重要部分是在查询中包含原始数组文档以进行更新。

    给出以下形式的文件:

    {
        _id: "foo",
        arrayField: [
            {
                a: 1,
                b: 1
            },
            {
                a: 2,
                b: 1
            }
        ]
    }
    

    假设您想将{ a: 1, b: 1 }移动到另一个字段,可能称为someOtherArrayField,您可能希望执行类似的操作。

    var doc = db.col.findOne({_id: "foo"});
    var arrayDocToMove = doc.arrayField[0];
    db.col.update({_id: "foo", arrayField: { $elemMatch: arrayDocToMove} }, { $pull: { arrayField: arrayDocToMove }, $addToSet: { someOtherArrayField: arrayDocToMove } })
    

    我们使用$elemMatch的原因是为了确保我们要从数组中删除的字段在我们首次查询文档后没有更改。当与$pull结合使用时,它也不是必需的,但在这些情况下我通常过于谨慎。如果您的应用程序中没有并行性,并且您只有一个应用程序实例,则不一定非常必要。

    现在,当我们检查生成的文档时,我们得到:

    db.col.findOne()
    {
            "_id" : "foo",
            "arrayField" : [
                    {
                            "a" : 2,
                            "b" : 1
                    }
            ],
            "someOtherArrayField" : [
                    {
                            "a" : 1,
                            "b" : 1
                    }
            ]
    }