Search code examples
springmongodbspring-bootspring-repositories

How to use slice and count in the same query in MongoDB


I need to combine slice and count in the same query, let me explain how:

I have a collection which stores comments with his replies within in an array

{
    "_id" : ObjectId("5a6b14796ede6d5169ad68a7"),
    "_class" : "com.social.model.comment.FirstLevelComment",
    "contentId" : "5a12996de7e84e0001b93a91",
    "replies" : [ 
        {
            "_id" : ObjectId("5a6b151a6ede6d5169ad68b1"),
            "date" : ISODate("2018-01-26T11:46:34.202Z"),
            "text" : "Reply 1"
        }, 
        {
            "_id" : ObjectId("5a6b151d6ede6d5169ad68b2"),
            "date" : ISODate("2018-01-26T11:46:37.357Z"),
            "text" : "Reply 2"
        }, 
        {
            "_id" : ObjectId("5a6b15206ede6d5169ad68b3"),
            "date" : ISODate("2018-01-26T11:46:40.170Z"),
            "text" : "Reply 3"
        }, 
        {
            "_id" : ObjectId("5a6b15236ede6d5169ad68b4"),
            "date" : ISODate("2018-01-26T11:46:43.025Z"),
            "text" : "Reply 4"
        }, 
        {
            "_id" : ObjectId("5a6b15256ede6d5169ad68b5"),
            "date" : ISODate("2018-01-26T11:46:45.931Z"),
            "text" : "Reply 5"
        }
    ],
    "date" : ISODate("2018-01-26T11:43:53.578Z"),
    "text" : "This is the comment text"
}

Every First level comment is stored in a separate document, so to retrieve all comments belong to a content, I have to make a query matching by "contentId" field.

But, I only want to retrieve the first two replies of every comment, so I have to use the $slice operator.

But I have to retrieve too, the total amount of replies that a comment has, so can I do that in the same query?

I'm using spring boot with mongo repositories, so for now my query is like this

@Query(value = "{}", fields = "{ replies : { $slice : 2 }}")
public Page<FirstLevelComment> findByContentId(String contentId, Pageable page);

But don't know how to add the number of replies to that query.

EDIT: Added query as Alex P. said

db.comment.aggregate([
{$match:{contentId: "5a12996de7e84e0001b93a91"}},
{
  $project: { 
    _id: 1,
    _class: 1,
    contentId: 1,
    date: 1,
    text: 1,
    countSize: {$size: "$replies"},
    sl: {$slice: ["$replies", 2]}
  }
}])

Solution

  • If you'd directly aggregate on your mongo server you would have to do this:

    db.collection.aggregate([
    {
      $project: { 
        _id: 1,
        _class: 1,
        contentId: 1,
        date: 1,
        text: 1,
        countSize: {$size: "$replies"},
        sl: {$slice: ["$replies", 2]}
      }
    }
    ])
    

    When using aggregation framework in your Java application with Spring Data you can't use MongoRepository. You would have to use MongoTemplate instead.
    Have a look in the documentation for more details