Anukool
Anukool

Reputation: 812

how to group in mongoDB and return all fields in result

I am using aggregate method in mongoDB to group but when I use $group it returns the only field which I used to group. I have tried $project but it is not working either. I also tried $first and it worked but the result data is now in different format.

The response format I need looks like:

{
    "_id" : ObjectId("5b814b2852d47e00514d6a09"),
    "tags" : [],
    "name" : "name here",
    "rating" : "123456789"
}

and after adding $group in my query.response is like this, the value of _id changes. (and the $group is taking only _id, if i try any other keyword it throws an error of accumulator something. please explain this also.)

{
    "_id" :"name here" //the value of _id changed to the name field which i used in $group condition
}

I have to remove the duplicates in name field, without changing any structure and fields. also I am using nodeJS with mongoose, so please provide the solution that works with it.

Upvotes: 48

Views: 57034

Answers (5)

Krishna Mistry
Krishna Mistry

Reputation: 51

I wanted to group my collection by groupById field and store it as key value pairs having key as groupById and value as all the items of that group.

db.col.aggregate([{$group :{_id :"$groupById",newfieldname:{$push:"$"}}}]).pretty()

This is working fine for me..

Upvotes: 3

Sathish Kumar
Sathish Kumar

Reputation: 957

user2683814's solution worked for me but in my case, I have a counter accumulator when we replace the newRoot object, the count field is missing in the final stage so I've used $mergeObjects operator to get my count field back.

db.collection.aggregate([
 {
  $group: {
    _id: '$product',
    detail: { $first: '$$ROOT' },
    count: {
      $sum: 1,
    },
  },
},
{
  $replaceRoot: {
    newRoot: { $mergeObjects: [{ count: '$count' }, '$detail'] },
  },
}])

Upvotes: 18

s7vr
s7vr

Reputation: 75964

You can use below aggregation query.

$$ROOT to keep the whole document per each name followed by $replaceRoot to promote the document to the top.

db.col.aggregate([
  {"$group":{"_id":"$name","doc":{"$first":"$$ROOT"}}},
  {"$replaceRoot":{"newRoot":"$doc"}}
])

Upvotes: 95

Senthur Deva
Senthur Deva

Reputation: 787

You can use this query

db.col.aggregate([
                        {"$group" : {"_id" : "$name","data" : {"$first" : "$$ROOT"}}},
                        {"$project" : {
                            "tags" : "$data.tags",
                            "name" : "$data.name",
                            "rating" : "$data.rating",
                            "_id" : "$data._id"
                            }
                        }])

Upvotes: 3

Adnan Ahmed Ansari
Adnan Ahmed Ansari

Reputation: 326

When you group data on any database, it means you want to perform accumulated operation on the required field and the other field which will not be include in accumulated operation will be used in group like

 db.collection.aggregate([{
 $group: {
   _id: { field1: "", field1: "" },
   acc: { $sum: 1 }
 }}]

here in _id object will contains all other fields which you want to hold.

for your data you can try this

db.collection.aggregate([{
    $group: {
        _id: "$name",
        rating: { $first: "$rating" },
        tags: { $first: "$tag" },
        docid: { $first: "$_id" }
    }
},
{
    $project: {
        _id: "$docid",
        name: "$_id",
        rating: 1,
        tags: 1
    }
}])

Upvotes: 4

Related Questions