MongoDB aggregation, take an array of values and get their amount

61 Views Asked by At

this is my first time asking in StackOverflow and I hope I can explain what I'm aiming for. I've got documents that look like this:

    "_id" : ObjectId("5fd76b67a7e0fa652a297a9f"),
    "type" : "play",
    "session" : "5b0b5d57-c3ca-415f-8ef6-49bbd5805a23",
    "episode" : 1,
    "show" : 1,
    "user" : 1,
    "platform" : "spotify",
    "currentTime" : 0,
    "date" : ISODate("2020-12-14T13:40:51.906Z"),
    "__v" : 0
}

I'd like to fetch for a show and group them by episode. I've got this far with my aggregattion:

    const filter = { user, show, type: { $regex: /^(play|stop|close)$/ } }
    const requiredFields = { "episode": 1, "session": 1, "date": 1, "currentTime": 1 }
    // Get sessions grouped by episode
    const it0 = {
        _id: '$episode',
        session:
            {$addToSet:
                {_id: "$session",
                date:{$dateToString: { format: "%Y-%m-%d", date: "$date" }},
                averageOfSession: {$cond: [ { $gte: [ "$currentTime", 0.1 ] }, "$currentTime", null ] }
            },
            },
        count: { $sum: 1 }
    }
    // Filter unique sessions by session id and add them to a sessions field
    const reduceSessions = {$addFields:
            {sessions: {$reduce: {input: "$session",initialValue: [],in:
            {$concatArrays: ["$$value",{$cond: [{$in: ["$$this._id","$$value._id"]},[],["$$this"]]}]}
            }}}}

    const projection = { $project: { _id: 0, episode: "$_id", plays: {$size: '$sessions'}, dropoff: {$avg: "$sessions.averageOfSession"}, sessions: '$session.date', events: "$count" } }

        const arr = await Play.aggregate([
            { $match: filter }, {$project: requiredFields}, {$group: it0}, reduceSessions,
            projection,{ $sort : { _id : 1 } }
        ])

and this is what my result looks like so far:

    {
        "episode": 5,
        "plays": 4,
        "dropoff": 3737.25,
        "sessions": [
            "2020-11-15",
            "2020-11-15",
            "2020-11-16",
            "2020-11-15"
        ],
        "events": 4
    }...

What I'd like is for the 'sessions' array to be an object with one key for each distinct date which would contain the count, so something like this:

 {
        "episode": 5,
        "plays": 4,
        "dropoff": 3737.25,
        "sessions": {
            "2020-11-15": 3,
            "2020-11-16": 1
        },
        "events": 4
    }...

Hope that makes sense, thank you!!

1

There are 1 best solutions below

0
On

You can first map sessions into key-value pairs. Then $group them to add up the sum. Then use $arrayToObject to convert to the format you want.

This Mongo playground is referencing this example.