Here is how my documents look like:
{
id: 123,
tasks: {
5f6effae74a3802fe80d02a4: Object
5f6f289b73cc4e43546733bb: Object
5f6f28d873cc4e43546733bc: Object
5f6f291073cc4e43546733bd: Object,
5f6f291073cc4e43541211cc: Object,
5f6f291073cc4e43465662eq: Object
},
taskIds: [
5f6effae74a3802fe80d02a4,
5f6f289b73cc4e43546733bb,
5f6f28d873cc4e43546733bc,
5f6f291073cc4e43546733bd
]
}
I need to delete each object in tasks
that matches id
from taskIds
so I thought about mapping through taskIds
like this:
const tasksDocument = await db.collection.findOne({id: 123})
tasksDocument.taskIds.map(async (id) => await tasksDocument.updateOne({ $unset: { [`tasks.${[id]}`]: "" } }))
But I'm wondering if there is cleaner way to do it without mapping?
If you're using Mongo version 4.2+ you can use pipelined update which allows you to use aggregation operators in an update.
Our strategy will be to convert the object to an array, filter it with the taskIds
and then converting back to an object, we will achieve this by using operators like $arrayToObject
, $objectToArray
, $filter
and more.
db.collection.update(
{
'id': 123
},
[
{
'$set': {
tasks: {
$arrayToObject: {
$filter: {
input: {$objectToArray: '$tasks'},
as: 'task',
cond: {
$eq: [
{
$size: {
$setIntersection: [['$$task.k'], '$taskIds']
}
},
0
]
}
}
}
}
}
}
])
For older Mongo versions you have to split this into 2 calls and do it in code similar to your solution (just having one call to $unset
instead of multiple).
const tasksDocument = await db.collection.findOne({id: 123});
let unsetArr = tasksDocument.taskIds.map(v => `tasks.${v}`);
await db.collection.updateOne({id: 123}, {$unset: unsetArr});
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.