I am working on MongoDB, which has a model as below:
const appJobSchema = new mongoose.Schema({
data: [
{ type: Schema.Types.Mixed }
],
stat: {
dataCount: { type: Number, default: 0 },
}
})
What I need to do is to update a few records in the array field, at the same time update the latest array length to the stat.dataCount field.
export async function updateDataById(id: string, records: any[]) {
return await model.updateOne({ '_id': id }, {
'$addToSet': { 'data': { '$each': records } } ,
'$set': {
'stat.dataCount': { $size: "$data" }
}
});
}
But I got an error saying:
UncaughtException: Cast to Number failed for value "{ '$size': '$data' }" (type Object) at path "stat.dataCount"
Any idea how I would do it?
Update
First try on the pipeline:
return await model.updateOne({'_id':id},
[
{
"$set": {
"data": {
$concatArrays: [ "$data", records ]
}
}
},
{
'$set': {
'stat.dataCount': { $size: "$data" } }
}
]);
It is working, but the problem is that solely adding values to the data array would cause duplicate values, and that is why I have to use $addToSet in order to remove the duplicates.
Second try on the pipeline:
Model.updateOne({'_id':id},
[
{ '$addToSet': { 'data': { '$each': records } }, '$inc':{ 'runCount': 1 } ,
{
'$set': {
'stat.dataCount': { $size: "$data" } }
}
]);
It throws out:
UncaughtException: Invalid update pipeline operator: "$addToSet".
Same for $inc.
Finally get it working by $setUnion with pipeline,
await Model.updateOne({'_id':id},
[
{
"$set": {
"data": {
$setUnion: [ "$data", records ]
}
}
},
{
'$set': {
'stat.dataCount': { $size: "$data" } }
},
]);
But what if I need to use $inc? It still seems a problem.
$incis the update operator, since you change it to pipeline, you should revamp to$setand$sumto increment the value:{ $set: { 'runCount': { $sum: [ '$runCount', 1] } } }