如何从 Mongo DB 中的子文档数组中删除匹配条件的子文档
Posted
技术标签:
【中文标题】如何从 Mongo DB 中的子文档数组中删除匹配条件的子文档【英文标题】:How to remove a subdocument matching a condition from an array of subdocuments in Mongo DB 【发布时间】:2022-01-09 18:26:13 【问题描述】:我有一个 MongoDB 数据库,其中包含以下格式的文档:
"name": "",
"surname": "",
"ssn": "",
"tests": [
"date": "",
"attending": [
"id": "",
"role": ""
]
]
文档包含每个人的测试列表及其相关信息。我想从每个文档中仅删除在某个日期(2019-02-22)之后由某个护士(id = 0187)执行的子文档(属于 tests 数组)。
由于所有日期都以 string 格式保存,因此我使用$dateFromString
运算符以下列方式进行日期比较:
db.Vaccinations.aggregate([
"$match":
"$expr":
"$and": [
"$gte": [
"$dateFromString": "dateString": "$tests.date",
ISODate("2019-02-22T00:00:00Z")
],
"tests.attending.id" : "0187"
]
])
但是我无法使用$pull
运算符来删除相应的子文档。是否可以这样做还是$pull
是错误的运营商?
【问题讨论】:
$pull 与 update 操作一起使用 - 删除匹配的数组元素。 @prasad_ 那么是否可以在没有聚合管道的情况下比较日期? 是的。您可以在 update 操作查询过滤器中使用$expr
。
您能否将数据修复为有效的 JSON?该数组已打开但未关闭,并且不清楚您的数据如何,即护士的身份。 you can use something like this检查语法
@Takis_ 现在应该修复了。关于数据,所有字段都只是字符串(对于护士 ID,它是一个四位数的字符串)。
【参考方案1】:
查询
从测试中只保留那些 或date < "2019-02-22"
nurse != "0187"
这样一来,必须在日期之前通过测试或由其他护士完成测试。
使用路径“$test.attending.id”检查nurse != "0187"
以获取该测试的所有ID(一个数组),并测试与["0187"]
的交集是否为空=> 护士没有进行测试.
*您可以根据需要使用 updateOne 或 updateMany
*如果日期格式相同,我没有使用$dateFromString
YYYY-MM-DD
比较会起作用,但通常将日期保存在数据库中,这会使事情变得更容易和更快。
Test code here
update(
,
["$set":
"tests":
"$filter":
"input": "$tests",
"cond":
"$or":
["$lt": ["$$test.date", "2019-02-22"],
"$eq":
["$setIntersection": [["0187"], "$$test.attending.id"], []]],
"as": "test"])
【讨论】:
我认为使用此解决方案,如果其中一项测试符合条件,则与该人相关的所有测试都将被删除,但我的目的是仅删除该护士在该日期之后进行的测试 用样本数据测试它,并发送一个无法修复它的链接,如果日期 如果那位护士在主治阵列中但不是一个人,您可能想继续进行测试?可以的话举个例子 不,我只想删除该护士在该日期之后所做的测试,这两个条件必须同时为真,因此如果该护士在指定日期之前进行了测试,那么我应该保留它测试 你说得对,我在"$test.attending.id"
之前输入了错误,而不是"$$test.attending.id"
,我认为现在没问题,可以满足您的需要。以上是关于如何从 Mongo DB 中的子文档数组中删除匹配条件的子文档的主要内容,如果未能解决你的问题,请参考以下文章