从嵌套对象数组中删除对象 MongoDB

3
我可以帮助翻译以下内容,这是与志愿者信息相关的编程问题。其中志愿者被列为一个对象数组,我能够显示每个志愿者的所有班次,但是从数组中删除一个志愿者对我来说很困难:
样本数据:
"_id" : ObjectId("59180305c19dbaa4ecd9ee59"),
    "where" : "Merchandise tent",
    "description" : "Sell gear at the merchandise tent.",
    "shifts" : [
            {
                    "dateNeeded" : ISODate("2017-06-23T00:00:00Z"),
                    "timeslot" : "8:00 - NOON",
                    "needed" : 2,
                    "_id" : ObjectId("591807546a71c3a57d1a2105"),
                    "volunteers" : [
                            {
                                    "fullname" : "Mary Mack",
                                    "phone" : "1234567890",
                                    "email" : "mary@gmail.com",
                                    "_id" : ObjectId("591ce45bc7e8a8c7b742474c")
                            }
                    ]
            },

我可以帮助您翻译。这段文字涉及编程相关内容。

我拥有的数据包括: _id、地点、班次时间、班次日期和志愿者电子邮件。

有人能帮帮我吗?假设玛丽·麦克想要取消在商品帐篷上早上8点到中午的班次。她可能还被列入其他班次,但我们只想从这个班次中删除她。


@D-reaper 这个问题的标签错误地打上了angular和javascript。实际上,它是在询问一个MongoDB操作。 - Neil Lunn
考虑到我正在使用AngularJS和MongoDB,我不知道是否有一种方法可以使用AngularJS更新数组,然后提交更改,或者是否必须通过MongoDB完成所有操作。我相信有几种方法,对吧? - mcadio
实际上更新数据库吗?不是的。您需要向 MongoDB 发出命令。客户端中的数组操作不会更新数据库。 - Neil Lunn
我知道这一点,但我认为在AngularJS中拼接数组然后在MongoDB中更新记录可能会更容易,因为我不确定如何在MongoDB本身中实现它。看起来有多种方法,但是我在下面得到了一个很好的答案。谢谢! - mcadio
2个回答

4
您可以通过将“文档”和所需的“shifts”数组条目作为查询表达式指定来执行此操作。然后,使用匹配数组索引的位置性$运算符$pull进行应用:
db.collection.update(
 { "_id": ObjectId("59180305c19dbaa4ecd9ee59"), "shifts.timeslot": "8:00 - NOON" },
 { "$pull": { "shifts.$.volunteers": { "fullname": "Mary Mack" } } }
)

在这种情况下,这样做是可以的,因为您只想在嵌套结构中“匹配”“外部”数组,而$pull具有自己的查询参数,以确定要删除的数组条目。但是,请注意使用“嵌套数组”的时候一定要小心。虽然像这样的$pull操作是有效的,但是更新“内部”数组实际上并不可行,因为位置 $ 操作符仅匹配满足条件的“第一个”元素。因此,在多个班次中,“Mary Mack”这个例子只能匹配到找到的第一个“班次”数组条目。

谢谢!我一直在尝试并且已经接近成功,但是不确定它是否有效。我还想过在AngularJS中对数组进行切片然后更新它,但是这似乎太复杂了。 - mcadio
@user3561890 虽然您可以在客户端中操作数组并保存详细信息,但这样做并不是很“安全”。在实际环境中,您可能会冒着其他进程已更新数据并覆盖这些操作的风险。另一件事情是,嵌套数组不是最好的设计模式。在我看来,我会将您的结构“展平”,将“班次”信息包含在“志愿者”的顶层列表中,而不是将每个班次的志愿者列表嵌入其中。 - Neil Lunn
谢谢Neil。这很有帮助。我正在尝试将我的大量前端代码转换为后端,就处理而言。 - mcadio

1

试试这个

db.example.update(
 {},
 { $unset: {"Mary Mack":1}},
 false, true
)

1
$unset 可以移除文档属性。OP 正在询问如何从数组中移除一个条目。 - Neil Lunn
这是真的。我肯定想从数组中删除整个对象,但我非常感谢你的想法。 - mcadio
1
最好能够解释一下为什么你认为这是回答提问者问题的答案,而不仅仅是发布一段代码块。 - Arya McCarthy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接