Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MongoDB reduce nested

Tags:

json

mongodb

I have a collection of a class that looks something like that:

[
  {
    "_id": 1,
    "title": "dummy title",
    "assignments": [
        {
            "_id": 1,
            "name": "a1",
            "members": [
               {
                   "_id": 11,
                   "full_name": "john doe",
                   "aga": 18
               },
               {
                   "_id": 12,
                   "full_name": "john doe2",
                   "aga": 18
               } 
            ]
        }
    ],
    "settings": [
      {
        "type": "light",
        "status": "enabled"
      },
      {
        "type": "flare",
        "status": "disabled"
      },
      {
        "type": "toolbar",
        "status": "enabled"
      }
    ]
  }
]

I have 2 nested documents here "assignments" which have a nested "members" and "settings". the result i want should look something like that:

{
    "_id": 1,
    "title": "dummy title",
    "assignments": [
        {
            "_id": 1,
            "name": "a1",
            "member_ids": [11, 18]
        }
    ],
    "active_settings": ["light", "toolbar"]
  }

Meaning in each "assignment" I should only return the ids of the members and not the whole member data. and in settings I should only return the settings that are set to "active"

is it possible?

Playground here: https://mongoplayground.net/p/Le4BdTm_gOv

like image 498
user2101699 Avatar asked Sep 08 '26 22:09

user2101699


2 Answers

You can try with $map to go one by one. $mergeObjects helps to merge the output value with same object

[
  {
    $project: {
      title: 1,
      assignments: {
        $map: {
          input: "$assignments",
          in: {
            $mergeObjects: [
              "$$this",
              {
                members: {
                  $map: {
                    input: "$$this.members",
                    in: "$$this._id"
                  }
                }
              }
            ]
          }
        }
      },
      active_settings: {
        $reduce: {
          input: "$settings",
          initialValue: [],
          in: {
            $cond: [
              {
                $eq: [
                  "$$this.status",
                  "enabled"
                ]
              },
              {
                $setUnion: [
                  "$$value",
                  [
                    "$$this.type"
                  ]
                ]
              },
              "$$value"
            ]
          }
        }
      }
    }
  }
]

Working Mongo playground

like image 197
varman Avatar answered Sep 10 '26 14:09

varman


You can try,

  • get assignments member ids using $map and $reduce
  • get active_settings using $reduce
db.collection.aggregate([
  {
    $project: {
      _id: 1,
      title: 1,
      assignments: {
        $map: {
          input: "$assignments",
          in: {
            _id: "$$this._id",
            name: "$$this.name",
            memberIds: {
              $reduce: {
                input: "$$this.members",
                initialValue: [],
                in: { $concatArrays: ["$$value", ["$$this._id"]] }
              }
            }
          }
        }
      },
      active_settings: {
        $reduce: {
          input: "$settings",
          initialValue: [],
          in: {
            $cond: [
              { $eq: ["$$this.status", "enabled"] },
              { $concatArrays: ["$$value", ["$$this.type"]] },
              "$$value"
            ]
          }
        }
      }
    }
  }
])

Playground

like image 31
turivishal Avatar answered Sep 10 '26 15:09

turivishal