Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I $concat fields in an array of objects?

What I have

I have the following documents coming into my aggregation pipeline:

[
    { 
        "email" : "[email protected]", 
        "name"  : "Organization Name",  
        "users" : [
            {
                "lastName"  : "Nye", 
                "firstName" : "Bill", 
                "email"     : "[email protected]"
            },
            {
                "lastName"  : "Rogers", 
                "firstName" : "Mr.", 
                "email"     : "[email protected]"
            }
        ]
    },
    ...
]

What I want

Using$project I want to $concat the firstName and lastName fields within each of the array subdocuments to get the following result:

{ 
    "email" : "[email protected]", 
    "name"  : "Organization Name",  
    "users" : [
        {
            "name"  : "Bill Nye", 
            "email" : "[email protected]"
        },
        {
            "name"  : "Mr. Rogers", 
            "email" : "[email protected]"
        }
    ]
}

What I've tried - Attempt #1

I've tried the following aggregation:

db.organizations.aggregate([
    {
        $project: {
            email : 1,
            name  : 1,
            users : {
              name  : { $concat : [ "$users.firstName", " ", "$users.lastName" ] },
              email : 1
            }
        }
    }
]);

... but I get the following error:

$concat only supports strings, not Array

What I've tried - Attempt #2

I've also tried the following aggregation:

db.organizations.aggregate([
    {
        $project: {
            email : 1,
            name  : 1,
            users : {
              name  : { $concat : [ "$firstName", " ", "$lastName" ] },
              email : 1
            }
        }
    }
]);

... but name always returns null.

I feel as if this should be a relatively simple thing to do, however, I'm completely stumped.

How do I get the results that I'm looking for?

like image 462
docksteaderluke Avatar asked Jul 06 '16 17:07

docksteaderluke


1 Answers

You can simply do this by $projecting your documents and use the $map aggregation variable operator to apply the $concat expression to each item in an array and returns an array with the applied results.

db.organizations.aggregate(
    [
        { "$project": { 
            "email": 1, 
            "name": 1, 
            "users": { 
                "$map": { 
                    "input": "$users", 
                    "as": "u", 
                      "in": { 
                          "name": { "$concat" : [ "$$u.firstName", " ", "$$u.lastName" ] }, 
                          "email": "$$u.email" 
                      } 
                }
            } 
        }} 
    ]
)
like image 103
styvane Avatar answered Sep 29 '22 07:09

styvane