Theres a several old questions (2015/2016) about doing an upsert with $inc that has a default value. The consensus seemed to be do multiple DB calls. I'm hoping there is a more modern approach to this now. I'm using Mongo 5.0.9.
I found this example that states you can now use $cond in update aggregation pipelines. I tried the following: https://stackoverflow.com/a/62819768/1795570
Trying to convert it to my problem I came up with:
const result = await context.params.tenantDb.collection('counters').findOneAndUpdate({
// Filter
name: options.name,
}, {
// Data
$set: {
value: {
$cond: {
if: {$eq:[{$type:"$value"} , "missing"]},
then: 1000, // it's the upsert case
else: { // it's the update case
$inc: {
value: 1
}
}
}
},
},
}, {
// Mongo Options
returnDocument: 'after',
name: options.name,
upsert: true,
});
This however just adds the entire $cond as the value to my document.
value: {
_id: new ObjectId("62ab8829d8ea984d839e10f3"),
name: 'my_counter',
value: { '$cond': [Array] }
},
Is it possible to do this?
CodePudding user response:
You will be able to achieve that with this, you're missing [] that will help you to use the aggregation framework, then you should have this
You will be able to achieve that with this, you 're missing [] that will help you to use the aggregation framework, then you should have this
const result = await context.params.tenantDb.collection('counters').findOneAndUpdate({
// Filter
name: options.name,
}, [{
$set: {
value: {
$cond: {
if: {
$eq: [{
$type: "$value"
},
"missing"
]
},
then: 1000,
// it's the upsert case
else: {
$add: [
"$value",
1
]
}
}
},
}
}], {
// Mongo Options
returnDocument: 'after',
name: options.name,
upsert: true,
multi: true
});