challet
challet

Reputation: 972

Merge two fields in one array

From a document having two fields, for instance "player_1" and "player_2". I'd like to aggregate them by merging them as an undifferenciated field. The next step will be to count the number of times a value appears no matter from one field or the other. For instance :

{
   _id : ObjectId("52f0795a58c5061aa34d436a"),
   "game_id": 765
   "player_1" : 1,
   "player_2" : 2
}

Would results to :

{
   "game_id": 765,
   "player" : 1
},
{
   "game_id": 765,
   "player" : 2
}

Because this fields are not arrays, I haven't found a solution to aggregate them this way.

For instance the following aggregation command doesn't understand I'm tryining to fetch document fields

[
{ $project: { 
    game_id: true, 
    player: { $setUnion: [['$player_1'], ['$player_2']] } }
},
{ $unwind: '$player' }
]

and results :

{
   "game_id": 765,
   "player": "$player_1" 
},
{
   "game_id": 765,
   "player" : "$player_2"
}

Upvotes: 3

Views: 3050

Answers (1)

Sede
Sede

Reputation: 61293

You need to use the $map operator with the $literal operator to return an array of "players".

db.collection.aggregate([
    { $project: {
        "game_id": 1, 
        "player": { 
            "$map": { 
                input: { $literal: [ "p1", "p2" ] }, 
                as: "p", 
                in: { 
                    $cond: [ 
                        { $eq: [ "$$p", "p1" ] }, 
                        "$player_1", 
                        "$player_2"
                    ]
                }
            }
        }
    }}, 
    { $unwind: "$player" }
])

Which yields:

{
        "_id" : ObjectId("52f0795a58c5061aa34d436a"),
        "game_id" : 765,
        "player" : 1
}
{
        "_id" : ObjectId("52f0795a58c5061aa34d436a"),
        "game_id" : 765,
        "player" : 2
}

Upvotes: 4

Related Questions