Paul Ryan Lucero
Paul Ryan Lucero

Reputation: 551

MongoDB how to get count of comments + replies

So I have this structure in my MongoDB instance.

{
  "post_body": "test",
  "author": "test1",
  "comments":[
    {
      "comment_body": "comment test",
      "comment_author": "test2",
      "replies": [
        {
          "reply_body": "reply test1",
          "reply_author": "test3"
        },
        {
          "reply_body": "reply test2",
          "reply_author": "test2"
        }
      ]
    }
  ]
}

And I want to get the total count of comments + replies.

So my desired output should be

{
    "post_body": "test"
    "author": "test1",
    "comment_count": 3
}

So far using $project only returns the total count of comments only. I want to get the total of comments + replies

Upvotes: 1

Views: 740

Answers (2)

Clement Amarnath
Clement Amarnath

Reputation: 5466

Using Aggregation Pipeline we can get the desired result

Below query uses Pipeline Stages $project, $unwind and Pipeline operators $size and $sum

db.collection_name.aggregate([
  { $project: {
     "post_body": 1, 
     "author": 1,
     "comments":1,
     "comments_size":{$size: "$comments" }
    }
  }, 
  { $unwind: "$comments" }, 
  { $project: {
     "post_body": 1, 
     "author": 1,
     "comments":1,
     "comments_size":1, 
     "replies_size" : {$size: "$comments.replies"} 
    }
  },
  { $project: {
     "_id":0, 
     "post_body": 1,
     "author": 1,
     "comments_count":{$sum:["$comments_size", "$replies_size"]}
    }
  }
])

First part of the aggregation query uses $project and we are just projecting the required attributes to next stage and also we are finding the size of the comments array. The size of the comments array is stored in a temporary attribute comments_size

Second part uses $unwind to break the nested array in comments and comments.replies, the comments array is unwinded and comments.replies array is kept unaltered

Third part uses $project to find the size of the replies and it is stored in a temporary attribute replies_size

Fourth and final part uses $project again with $sum of comments_size and replies_size to get the desired result

Upvotes: 0

Zouhair Elhadi
Zouhair Elhadi

Reputation: 106

import pymongo
from bson.objectid import ObjectId
myclient = pymongo.MongoClient("mongodb://localhost:27017/")
db = myclient["test"]
comments_col = db["comments"]
doc = {
    "post_body": "test",
    "author": "test1",
    "comments": [
        {
            "comment_body": "comment test",
            "comment_author": "test2",
            "replies": [
                {
                    "reply_body": "reply test1",
                    "reply_author": "test3"
                },
                {
                    "reply_body": "reply test2",
                    "reply_author": "test2"
                },
            ]
        }
    ]
}

def insert(doc1):
    id_comment = comments_col.insert(doc1)
    return id_comment
def find(id_comment):
    comment = comments_col.find_one({"_id": ObjectId(str(id_comment))})
    return comment
if __name__ == "__main__":
    id_comment = insert(doc)
    comment = find(id_comment)
    print("comments with replies : ", comment["comments"])
    print("\n")
    print("replies : ", comment["comments"][0]["replies"])
    print("\n")
    print("comment_author : ", comment["comments"][0]["comment_author"])
    print("\n")
    print("comment_body : ", comment["comments"][0]["comment_body"])

Upvotes: 1

Related Questions