Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Aggregate Query in Mongodb returns specific field

Document Sample:

{
    "_id" : ObjectId("53329dfgg43771e49538b4567"),
    "u" : {
        "_id" : ObjectId("532a435gs4c771edb168c1bd7"),
        "n" : "Salman khan",
        "e" : "[email protected]"
    },
    "ps" : 0,
    "os" : 1,
    "rs" : 0,
    "cd" : 1395685800,
    "ud" : 0
}

Query:

db.collectiontmp.aggregate([
            {$match: {os:1}},
            {$project : { name:{$toUpper:"$u.e"} , _id:0 } },
            {$group: { _id: "$u._id",total: {$sum:1} }},
            {$sort: {total: -1}}, { $limit: 10 }
             ]);

I need following things from the above query:

  1. Group by u._id
  2. Returns total number of records and email from the record, as shown below:

    { "result": [ { "email": "", "total": "" }, { "email": "", "total": "" } ], "ok": 1 }

like image 370
Anubhav Avatar asked Aug 21 '14 05:08

Anubhav


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.

What does MongoDB aggregation return?

In MongoDB, aggregation operations process the data records/documents and return computed results. It collects values from various documents and groups them together and then performs different types of operations on that grouped data like sum, average, minimum, maximum, etc to return a computed result.

How do I fetch a specific column in MongoDB?

Fetch selective field from collection based on a criteria If we want to fetch only the "user_id" for all documents from the collection 'userdetails' which hold the educational qualification "M.C.A.", the following mongodb command can be used : >db. userdetails. find({"education":"M.C.A."},{"user_id" : 1}).

What does Mongoose aggregate return?

Returns: A cursor to the documents produced by the final stage of the aggregation pipeline operation, or if you include the explain option, the document that provides details on the processing of the aggregation operation. If the pipeline includes the $out operator, aggregate() returns an empty cursor.


1 Answers

The first thing you are doing wrong here is not understanding how $project is intended to work. Pipeline stages such as $project and $group will only output the fields that are "explicitly" identified. So only the fields you say to output will be available to the following pipeline stages.

Specifically here you "project" only part of the "u" field in your document and you therefore removed the other data from being available. The only present field here now is "name", which is the one you "projected".

Perhaps it was really your intention to do something like this:

db.collectiontmp.aggregate([
    { "$group": {
        "_id": {
           "_id": "$u._id",
           "email": { "$toUpper": "$u.e" }
        },
        "total": { "$sum": 1 },
    }},
    { "$project": {
        "_id": 0,
        "email": "$_id.email",
        "total": 1
    }},
    { "$sort": { "total": -1 } },
    { "$limit": 10 }
])

Or even:

db.collectiontmp.aggregate([
    { "$group": {
        "_id": "$u._id",
        "email": { "$first": { "$toUpper": "$u.e" } }
        "total": { "$sum": 1 },
    }},
    { "$project": {
        "_id": 0,
        "email": 1,
        "total": 1
    }},
    { "$sort": { "total": -1 } },
    { "$limit": 10 }
])

That gives you the sort of output you are looking for.

Remember that as this is a "pipeline", then only the "output" from a prior stage is available to the "next" stage. There is no "global" concept of the document as this is not a declarative statement such as in SQL, but a "pipeline".

So think Unix pipe "|" command, or otherwise look that up. Then your thinking will fall into place.

like image 106
Neil Lunn Avatar answered Oct 13 '22 01:10

Neil Lunn