Home > Net >  How to addfields in MongoDB retrospectively
How to addfields in MongoDB retrospectively

Time:03-05

I have a schema that has a like array. This array stores all the people who have liked my post. I just added a likeCount field as well but the likeCount fields default value is 0. How can I create an addfields in mongoDB so that I can update the likeCount with the length of the like array?

I am on a MERN stack.

CodePudding user response:

I am assuming you have a data structure like this:

{
   postId: "post1",
   likes: [ "ID1", "ID2", "ID3" ]
}

There is almost no reason to add a likeCount field. You should take the length of the likes array itself. Some examples:

db.foo.insert([
    {'post':"P1", likes: ["ID1","ID2","ID3"]},
    {'post':"P2", likes: ["ID1","ID2","ID3"]},
    {'post':"P3", likes: ["ID4","ID2","ID6","ID7"]}
]);

// Which post has the most likes?
db.foo.aggregate([
    {$addFields: {N: {$size: "$likes"}}},
    {$sort: {"N":-1}}
    //, {$limit: 2}  // optionally limit to whatever                              
]);

// Is ID6 in likes?                                                               
// $match of a scalar to an input field ('likes') acts like                       
// $in for convenience:                                                           
db.foo.aggregate([  {$match: {'likes':'ID6'}}  ]);

// Is ID6 OR ID3 in likes?                                                        
db.foo.aggregate([  {$match: {'likes':{$in:['ID6','ID3']}}}  ]);

// Is ID2 AND ID7 in likes?                                                       
// This is a fancier way of doing set-to-set compares instead                     
// of a bunch of expression passed to $and:                                       
var targets = ['ID7','ID2'];
db.foo.aggregate([
    {$project: {X: {$eq:[2, {$size:{$setIntersection: ['$likes', targets]}} ]} }}
]);

// Who likes the most across all posts?                                           
db.foo.aggregate([
    {$unwind: '$likes'},
    {$group: {_id: '$likes', N:{$sum:1}} },
    {$sort: {'N':-1}}
]);

CodePudding user response:

This is how to update all the documents with the respective likeCount values the first time:

db.collection.update({},
[
 {
   $addFields: {
    likeCount: {
      $size: "$like"
     }
   }
 }
],
{
  multi: true
})

Every next time somebody or multiple people are added to the like array , you may set the likeCount with the $size or you may increase the count with $inc operation.

Afcourse as @Buzz pointed below it is best to leave the array count() in the read code since updating every time like count() it will be an expensive operation leading to performance implication under heavy load ...

playground

  • Related