31

I need to return array of string with mongodb aggregation. I did the following:

db.users.aggregate([{$group: {_id:"$emails.address"}}])

It return:

{ "_id" : [ "[email protected]" ] }
{ "_id" : [ "[email protected]" ] }
{ "_id" : [ "[email protected]" ] }

Is there a way to return array of string like this one:

["[email protected]","[email protected]","[email protected]"]

thank You very much anyone who taking your time for helping me..

EDIT

Adding data:

{
    "_id" : "ukn9MLo3hRYEpCCty",
    "createdAt" : ISODate("2015-10-24T03:52:11.960Z"),
    "emails" : [
        {
            "address" : "[email protected]",
            "verified" : false
        }
    ]
}
{
    "_id" : "5SXRXraariyhRQACe",
    "createdAt" : ISODate("2015-10-24T03:52:12.093Z"),
    "emails" : [
        {
            "address" : "[email protected]",
            "verified" : false
        }
    ]
}
{
    "_id" : "WMHWxeymY4ATWLXjz",
    "createdAt" : ISODate("2015-10-24T03:52:12.237Z"),
    "emails" : [
        {
            "address" : "[email protected]",
            "verified" : false
        }
    ]
}
4
  • can you post your data Commented Oct 30, 2015 at 0:58
  • hi @ScottStensland i have added the data,,,thank You.. Commented Oct 30, 2015 at 1:41
  • hi r u meaning to return in name with array values pair or just return only in array? Commented Oct 30, 2015 at 4:10
  • hi @HaRLoFei just return only in array. any idea?? Commented Oct 30, 2015 at 4:23

2 Answers 2

42

The .aggregate() method always returns Objects no matter what you do and that cannot change.

For your purpose you are probably better off using .distinct() instead, which does just return an array of the distinct values:

db.users.distinct("emails.address");

Which is exactly your desired output:

["[email protected]","[email protected]","[email protected]"]

If you really want to use .aggregate() then the tranformation to just the values needs to happen "outside" of the expression in post processing. And you should also be using $unwind when dealing with arrays like this.

You can do this with JavaScript .map() for example:

db.users.aggregate([
    { "$unwind": "$emails" },
    { "$group": { "_id": "$emails.address" } }
]).map(function(el) { return el._id })

Which gives the same output, but the .map() does the transformation client side instead of on the server.

Sign up to request clarification or add additional context in comments.

2 Comments

is there a way to make it in server side, as client side mapping will slow down performance
@ChiDov I've answered doing on mongodb here: stackoverflow.com/a/46599310/4308032 It will give you an array, but it will be still embedded in object.
30

What Blakes Seven has answered is right.

The .aggregate() method always returns Objects no matter what you do and that cannot change.

However, that does not mean you cannot put them in an array and return the array in an object.

I believe that mapping in array in the database itself would be more better, as your node server can still be available to other requests.

db.users.aggregate([
     { "$unwind": "$emails" },
     { "$group": { "_id": null, emails:{$push:"$emails.address"} } },
     { "$project":{emails:true,_id:false}}
 ])

This will return:

{ "emails" : [ "[email protected]", "[email protected]", "[email protected]" ] }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.