5

I'm having trouble with my aggregate function. I'm trying to get the users most common orders from the database but I'm only returning the name and the count. I've tried using the $project operator but I can't seem to make it return anything other than what's in the $group statement.

Here is my current aggregate function:

OrderModel.aggregate(
        {$unwind: "$products"},
        {$match: { customerID: customerID }},
        {$group: { _id: "$products.name", count: {$sum:1}}},
        {$project: {name: "$_id", _id:0, count:1, active:1}},
        {$sort: {"count" : -1}},
        {$limit: 25 })

This just produces an output as follows {"count":10, "name": foo"} whereas I want to return the whole object; embedded docs and all. Any ideas where I'm going wrong?

Edit- Added example document and expected output

Document:

{
    "charge": {},
        "captured": true,
        "refunds": [
        ],
        "balance_transaction": "txn_104Ics4QFdqlbCVHAdV1G2Hb",
        "failure_message": null,
        "failure_code": null,
        "amount_refunded": 0,
        "customer": "cus_4IZMPAIkEdiiW0",
        "invoice": null,
        "dispute": null,
        "statement_description": null,
        "receipt_email": null
    },
    "total": 13.2,
    "userToken": "cus_4IZMPAIkEdiiW0",
    "customerID": "10152430176375255",
    "_id": "53ad927ff0cb43215821c649",
    "__v": 0,
    "updated": 20140701082928810,
    "created": 20140627154919216,
    "messageReceived": false,
    "ready": true,
    "active": false,
    "currency": "GBP",
    "products": [
        {
            "name": "Foo",
            "active": true,
            "types": [
                {
                    "variants": [
                        {
                            "name": "Bar",
                            "isDefault": false,
                            "price": 13.2
                        }
                    ]
                }
            ]
        }
    ]
}

Expected outcome:

[
    {
        "name": "Foo",
        "active": true,
        "types": [
            {
                "variants": [
                    {
                        "name": "Bar",
                        "isDefault": false
                    }
                ]
            },
            {
                "variants": [
                    {
                        "name": "Something else",
                        "isDefault": false
                    }
                ]
            }
        ],
        "quantity": 10
   },
   {
       "name": "Another product",
       "active": true,
       "types": [
           {
               "variants": [
                   {
                       "name": "Bar",
                       "isDefault": false
                   }
               ]
           }
       ],
       "quantity": 7
   }

]

Thanks!

Neil Lunn
  • 148,042
  • 36
  • 346
  • 317
donpisci
  • 259
  • 3
  • 8
  • 23
  • Show a sample document from your collection. But if "customerID" is actually a grouping across documents then what you are doing will not work if you want the original documents back. Show source documents and your expected results. – Neil Lunn Jul 04 '14 at 10:32
  • @NeilLunn I've updated the post now. CustomerId is not a grouping across documents, just a field in this document. – donpisci Jul 04 '14 at 12:22

1 Answers1

12

Largely speaking here, $project relies on the "absolute path" to the field property in the document on the "right hand" side. Shortcuts such as 1 are just for where that element is actually the top level of the document.

Also you need to be able to retain fields when you $group, so this is where you use various grouping operators such as $first and $addToSet or $push to keep the information you are puling from the inner array. And you must $unwind twice here as well since you are combining "types" across documents, and you do not want just the $first in this case.

OrderModel.aggregate([
    { "$unwind": "$products" },
    { "$unwind": "$products.types" },
    { "$group": {
        "_id": "$products.name",
        "active": { "$first": "$products.active" },
        "types": { "$addToSet": "$products.types" },
        "quantity": { "$sum": 1 }
    }},
    { "$project": {
        "_id": 0,
        "name": "$_id",
        "active": 1,
        "types": 1,
        "quantity": 1
    }}
],function(err,results) {

});
Neil Lunn
  • 148,042
  • 36
  • 346
  • 317