King Julien
King Julien

Reputation: 11338

Return whole document from aggregation

I'm using the following query to fetch one most recent comment for every post in database:

db.comments.aggregate([
    {
        "$match": {
            "post_id": {
                "$in": [ObjectId("52c5ce24dca32d32740c1435"), ObjectId("52c5ce24dca32d32740c15ad")]
            }
        }
     },
     {
         "$sort": {"_id": -1}
     },
     {
        "$group": {
            "_id": "$post_id",
            "lastComment": {
                "$first": "$_id"
            }
        }
     }
])

I expect it to return the whole comment's document but it only returns the _id field of each document. So what would be the proper way to get all most recent comments as a whole document (or at least include some other fields)?

Upvotes: 9

Views: 9203

Answers (2)

whoami - fakeFaceTrueSoul
whoami - fakeFaceTrueSoul

Reputation: 17925

As suggested, we can do :

 {
    "$group": {
        _id: "$post_id",
        lastComment: { "$first": "$$CURRENT" }
    }
}

and then do use { '$replaceRoot': { 'newRoot': '$lastComment' } } on any mongodb server 3.4 or above to unwrap object from {lastComment:{actualEntireObj}},{lastComment:{actualEntireObj}} to {},{} this way it will get embedded $$ROOT document to the top level and replaces all other fields like _id returning from $group stage of aggregation.

    db.collection.aggregate([
    {
        "$match": {
            "post_id": {
                "$in": [ObjectId("52c5ce24dca32d32740c1435"), ObjectId("52c5ce24dca32d32740c15ad")]
            }
        }
    },
    {
        "$sort": { "_id": -1 }
    },
    {
        "$group": {
            _id: "$post_id",
            lastComment: { "$first": "$$CURRENT" }
        }
    },
    { '$replaceRoot': { 'newRoot': '$lastComment' } }
])

Upvotes: 4

Shad
Shad

Reputation: 4464

Currently you cannot get the whole comment document via single $first operator. But you can include other necessary fields (similar to _id field) during $group step:

{
    "$group": {
        _id: "$post_id",
        lastComment: { "$first": "$_id" },
        field_1: { "$first": "$field_1" },
        field_2: { "$first": "$field_2" },
        // ...
        field_N: { "$first": "$field_N" }
    }
}

According to this JIRA ticket: https://jira.mongodb.org/browse/SERVER-5916, the whole document will be available to return from aggregation operations from 2.5.3 version. It will be possible using new variables: $$ROOT or $$CURRENT:

{
    "$group": {
        _id: "$post_id",
        lastComment: { "$first": "$$CURRENT" }
    }
}

Upvotes: 23

Related Questions