Lets say you are making a simply todo app and you have a structure that looks like this:
{
[userId]: {
nextTaskId:3,
tasks: {
1: "take out the trash",
2: "pick up milk"
}
}
When adding a task, I'd like to create a new record using the the nextTaskId and also increment it. I have seen other examples using a aggregation function like $concat or the like, but that doesn't fit my usecase.
I'd like to be able to reference the field in my update, something like:
db.tasks.updateOne({_id:5}, {$inc:{nextId:1}, $set: {"tasks.$nextId":{"new task" }}})
the field does get incremented, however the tasks key is not 3, but $nextId and I also tried using it as a value, as in:
db.tasks.updateOne({_id:5}, {$inc:{nextId:1}, $set: {"tasks.3":{"$nextId" }}})
that doesn't work either. of course, I could do this by making 2 individual operations, one to get the next id and increment it, and another to create the new task record, but i'm hoping to do it with a single operation.
Any ideas?
CodePudding user response:
You can use update with aggregation pipeline to achieve the behaviour in one single update statement. Use $objectToArray
and $arrayToObject
to manipulate the tasks
array.
db.collection.update({
_id: 5
},
[
{
"$addFields": {
"tasks": {
"$objectToArray": "$tasks"
}
}
},
{
"$addFields": {
"nextTaskId": {
$add: [
"$nextTaskId",
1
]
},
tasks: {
"$concatArrays": [
"$tasks",
[
{
k: {
$toString: "$nextTaskId"
},
// your input for the new task
v: "next task"
}
]
]
}
}
},
{
"$addFields": {
"tasks": {
"$arrayToObject": "$tasks"
}
}
}
])
Here is the Mongo playground for your reference.