Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return specific field in aggregate

i am trying to aggregate the following data:

{
    "_id" : ObjectId("527a6b7c24a8874c078b9d10"),
    "Name" : "FirstName",
    "Link" : "www.mylink.com/123",
    "year" : 2013
}
{
    "_id" : ObjectId("527a6b7c24a8874c078b9d11"),
    "Name" : "FirstName",
    "Link" : "www.mylink.com/124",
    "year" : 2013
}
{
    "_id" : ObjectId("527a6b7c24a8874c078b9d12"),
    "Name" : "SecondName",
    "Link" : "www.mylink.com/125",
    "year" : 2013
}

I want to aggregate number of occurencies of Name field, but also want to return the corresponding Link field in the output of aggregate query. Now I am doing it like this (which does not return the Link field in the output):

db.coll.aggregate([

    { "$match": { "Year": 2013 } },

    { "$group": {
        "_id": {
            "Name": "$Name"
        },
        "count": { "$sum": 1 }
    }},
    { "$project": {
        "_id": "$_id",
        "count": 1
    }},

    { $sort: {
        count: 1
    } }
])

The above returns only Name field and count. But how can I also return the corresponding Link field (could be several) in the output of aggregate query?

Best Regards

like image 811
user1665355 Avatar asked Sep 09 '16 13:09

user1665355


People also ask

How do I get only certain fields in MongoDB aggregate?

You needed to add $push or $addToSet to maintain the $Link value in your grouping. $addToSet will allow for unique values in the array only, while $push will add all values, so use whichever at your discretion. $project and $sort are straightforward, rename and include/exclude whichever fields you would like.

How do I return a field in MongoDB?

Return All Fields in Matching Documents If you do not specify a projection document, the db. collection. find() method returns all fields in the matching documents.

What is the return type of aggregate?

An aggregate function always returns exactly one row, even when the input contains zero rows. Typically, if the input contained zero rows, the output is NULL. However, an aggregate function could return 0, an empty string, or some other value when passed zero rows.


1 Answers

db.coll.aggregate([
    { "$match": { "year": 2013 } },
    { "$group": {"_id": "$Name", "Link": {$push: "$Link"}, "count": { "$sum": 1 }}},
    { "$project": {"Name": "$_id", _id: 0, "Link": 1, "count": 1}},
    { $sort: {count: 1} }
])

Results in:

{ "Link" : [ "www.mylink.com/125" ], "count" : 1, "Name" : "SecondName" }

{ "Link" : [ "www.mylink.com/123", "www.mylink.com/124" ], "count" : 2, "Name" : "FirstName" }

Ok so the $match was correct except for a typo with 'Year' --> 'year'

The $group could be simplified a little bit. I removed an extra set of brackets so that you get id: 'FirstName' instead of id: { 'name': 'FirstName' } since we can reshape the _id to 'name' in the $project stage anyways.

You needed to add $push or $addToSet to maintain the $Link value in your grouping. $addToSet will allow for unique values in the array only, while $push will add all values, so use whichever at your discretion.

$project and $sort are straightforward, rename and include/exclude whichever fields you would like.

like image 83
dyouberg Avatar answered Oct 02 '22 07:10

dyouberg