I am working on mongodb which has model like the 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 to the mongodb array field - data, 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 would I 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 solely adding values to data array would cause the duplicate values, and that is why I have to use $addToSet in order to remove the duplicate.
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 seems still a problem.
As you are switching to the update pipeline to use the aggregation operator, the update operator is not supported. You need to switch to all aggregation operators, such as $sum
to replace the $inc
.
await Model.updateOne({'_id':id},
[
{
"$set": {
"data": {
$setUnion: [ "$data", records ]
},
"runCount": {
$sum: [ "$runCount", 1 ]
}
}
}
},
{
"$set": {
"stat.dataCount": { $size: "$data" }
}
},
]);