How to return array of string with mongodb aggrega

2019-01-15 20:09发布

问题:

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

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

It return:

{ "_id" : [ "a@a.com" ] }
{ "_id" : [ "b@a.com" ] }
{ "_id" : [ "c@a.com" ] }

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

["a@a.com","b@a.com","c@a.com"]

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" : "a@a.com",
            "verified" : false
        }
    ]
}
{
    "_id" : "5SXRXraariyhRQACe",
    "createdAt" : ISODate("2015-10-24T03:52:12.093Z"),
    "emails" : [
        {
            "address" : "b@a.com",
            "verified" : false
        }
    ]
}
{
    "_id" : "WMHWxeymY4ATWLXjz",
    "createdAt" : ISODate("2015-10-24T03:52:12.237Z"),
    "emails" : [
        {
            "address" : "c@a.com",
            "verified" : false
        }
    ]
}

回答1:

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:

["a@a.com","b@a.com","c@a.com"]

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.



回答2:

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" : [ "a@a.com", "b@a.com", "c@a.com" ] }