如何从 MongoDB 文档中的双重嵌套数组中删除元素。

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5228210/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 12:00:26  来源:igfitidea点击:

How to remove an element from a doubly-nested array in a MongoDB document.

mongodb

提问by rshepherd

I have a document structure something along the lines of the following:

我有一个类似以下内容的文档结构:

{
"_id" : "777",
"someKey" : "someValue",
"someArray" : [
    {
        "name" : "name1",
        "someNestedArray" : [
            {
                "name" : "value"
            },
            {
                "name" : "delete me"
            }
        ]
    }
  ]
}

I want to delete the nested array element with the value "delete me".

我想删除值为“删除我”的嵌套数组元素。

I know I can find documents which match this description using nested $elemMatch expressions. What is the query syntax for removing the element in question?

我知道我可以使用嵌套的 $elemMatch 表达式找到与此描述匹配的文档。删除相关元素的查询语法是什么?

回答by Gates VP

To delete the item in question you're actually going to use an update. More specifically you're going to do an update with the $pullcommand which will remove the item from the array.

要删除有问题的项目,您实际上将使用更新。更具体地说,您将使用$pull将从数组中删除项目的命令进行更新。

db.temp.update(
  { _id : "777" },
  {$pull : {"someArray.0.someNestedArray" : {"name":"delete me"}}}
)

There's a little bit of "magic" happening here. Using .0indicates that we know that we are modifying the 0th item of someArray. Using {"name":"delete me"}indicates that we know the exact data that we plan to remove.

这里发生了一些“魔法”。Using.0表示我们知道我们正在修改 的第 0 项someArray。Using{"name":"delete me"}表示我们知道我们计划删除的确切数据。

This process works just fine if you load the data into a client and then perform the update. This process works less well if you want to do "generic" queries that perform these operations.

如果您将数据加载到客户端然后执行更新,则此过程会正常工作。如果您想执行执行这些操作的“通用”查询,则此过程的效果较差。

I think it's easiest to simply recognize that updating arrays of sub-documents generally requires that you have the original in memory at some point.

我认为最简单的方法是简单地认识到更新子文档数组通常需要您在某个时候将原始文档保存在内存中。



In response to the first comment below, you can probably help your situation by changing the data structure a little

针对下面的第一条评论,您可能可以通过稍微更改数据结构来帮助您的情况

"someObjects" : {
  "name1":  {
        "someNestedArray" : [
            {
                "name" : "value"
            },
            {
                "name" : "delete me"
            }
        ]
    }
}

Now you can do {$pull : { "someObjects.name1.someNestedArray" : ...

现在你可以做 {$pull : { "someObjects.name1.someNestedArray" : ...

Here's the problem with your structure. MongoDB does not have very good support for manipulating "sub-arrays". Your structure has an array of objects and those objects contain arrays of more objects.

这是你的结构问题。MongoDB 对操作“子数组”没有很好的支持。你的结构有一个对象数组,这些对象包含更多对象的数组。

If you have the following structure, you are going to have a difficult time using things like $pull:

如果您有以下结构,您将很难使用以下内容$pull

array [
  { subarray : array [] },
  { subarray : array [] },
]

If your structure looks like that andyou want to update subarrayyou have two options:

如果您的结构看起来像这样并且您想要更新,subarray您有两个选择:

  1. Change your structure so that you can leverage $pull.
  2. Don't use $pull. Load the entire object into a client and use findAndModify.
  1. 更改您的结构,以便您可以利用$pull.
  2. 不要使用$pull. 将整个对象加载到客户端并使用findAndModify.

回答by Aryeh Armon

As @Melkor has commented (should probably be an answer as itself),

正如@Melkor 所评论的那样(本身应该是一个答案),

If you do not know the index use:

如果您不知道索引,请使用:

    {_id: TheMainID, "theArray._id": TheArrayID}, {$pull: 
    {"theArray.$.theNestedArray": {_id: theNestedArrayID}}}

回答by Cuong Le Ngoc

MongoDB 3.6 added $[]operator that facilitates updates to arrays that contain embedded documents. So the problem can be solved by:

MongoDB 3.6 添加了$[]运算符,便于更新包含嵌入文档的数组。所以问题可以通过以下方式解决:

db.test.update(
  { _id : "777" },
  {$pull : {"someArray.$[].someNestedArray" : {"name":"delete me"}}}
)

回答by rafiquenazir

Other example and usage could be like this:

其他示例和用法可能是这样的:

{

    "company": {
        "location": {
            "postalCode": "12345",
            "Address": "Address1",
            "city": "Frankfurt",
            "state": "Hessen",
            "country": "Germany"
        },
        "establishmentDate": "2019-04-29T14:12:37.206Z",
        "companyId": "1",
        "ceo": "XYZ"
    },
    "items": [{
            "name": "itemA",
            "unit": "kg",
            "price": "10"
        },
        {
            "name": "itemB",
            "unit": "ltr",
            "price": "20"
        }

    ]
}
  1. DELETE : Mongodb Query to delete ItemB:
  1. DELETE : Mongodb 查询删除 ItemB:
db.getCollection('test').update(   
    {"company.companyId":"1","company.location.city":"Frankfurt"},
    {$pull : {"items" : {"name":"itemB"}}}
)
  1. FIND: Find query for itemB:
  1. FIND:查找 itemB 的查询:
db.getCollection('test').find(
    {"company.companyId":"1","company.location.city":"Frankfurt","items.name":"itemB"},
    { "items.$": 1 }
)

3.UPDATE : update query for itemB:

3.UPDATE : 更新 itemB 的查询:

db.getCollection('test').update
(
 {"company.companyId":"1","company.location.city":"Frankfurt","items.name":"itemB"},
 { $set: { "items.$[].price" : 90 }}, 
   { multi: true });

回答by Sepp Renfer

From MongoDB 3.6 on you can use arrayFiltersto do this:

从 MongoDB 3.6 开始,您可以使用以下arrayFilters方法执行此操作:

db.test.update(
  { _id: "777" }, 
  { $pull: { "someArray.$[elem].someNestedArray": { name: "delete me" } } },
  { arrayFilters: [{ "elem.name": "name1"}] }
)

see also https://docs.mongodb.com/manual/reference/operator/update/positional-filtered/index.html#update-all-documents-that-match-arrayfilters-in-an-array

另见https://docs.mongodb.com/manual/reference/operator/update/positional-filtered/index.html#update-all-documents-that-match-arrayfilters-in-an-array