1

Suppose I have a simple collection like this:

[
  {
    Brands: [ 
                { BID: 1, Prods: [ { PID: 10 }, { PID: 11 } ] },
                { BID: 2, Prods: [ { PID: 20 }, { PID: 21 } ] }
           ]
  },
  {
    Brands: [
                { BID: 3, Prods: [ { PID: 30 }, { PID: 31 }, { PID: 32 } ] }
    ]
  }
]

I want to extract all unique PID from Prods, so the result would be:

[10,11,20,21,30,31,32]

I could get close to this doing this:

db.collection.aggregate([
  {
    $project: {
      "AllProds": {
        "$map": {
          "input": "$Brands.Prods",
          "as": "elem",
          "in": "$$elem.PID"
        }
      }
    }
  }
])

But the result is not a simple array, its a array of objects with the PID inside of it:

[
  {
    "AllProds": [
      [ 10, 11 ],
      [ 20, 21 ]
    ],
    "_id": ObjectId("5a934e000102030405000000")
  },
  {
    "AllProds": [
      [ 30, 31, 32 ]
    ],
    "_id": ObjectId("5a934e000102030405000001")
  }
]

Here is is the playground

3 Answers 3

1

You don't exactly require $map here. Just unwind the outer array, then the inner array and group them together

db.getCollection('SampleCollection').aggregate([
    {
        $unwind:"$Brands"
    },
    {
        $unwind:"$Brands.Prods"
    },
    {
        $group:
        {
            _id:null,
            PIDs: {$push:"$Brands.Prods.PID"}//use $addToSet instead of $push if you do not wish to allow duplicates
        }
    }    
])
Sign up to request clarification or add additional context in comments.

Comments

1
  • $group by null and make Brands array
  • $project, $reduce to iterate loop of $Brands array, $reduce to iterate loop of inner array of brands and concat arrays using $concatArrays
db.collection.aggregate([
  {
    $group: {
      _id: null,
      Brands: { $push: "$Brands.Prods.PID" }
    }
  },
  {
    $project: {
      _id: 0,
      Brands: {
        $reduce: {
          input: "$Brands",
          initialValue: [],
          in: {
            $concatArrays: [
              "$$value",
              {
                $reduce: {
                  input: "$$this",
                  initialValue: [],
                  in: { $concatArrays: ["$$value", "$$this"] }
                }
              }
            ]
          }
        }
      }
    }
  }
])

Playground

Comments

1

You can just do 2 more $unwind to flatten the arrays. Then use $group and $addToSet to get the result.

db.collection.aggregate([
  {
    $project: {
      "AllProds": {
        "$map": {
          "input": "$Brands.Prods",
          "as": "elem",
          "in": "$$elem.PID"
        }
      }
    }
  },
  {
    "$unwind": "$AllProds"
  },
  {
    "$unwind": "$AllProds"
  },
  {
    "$group": {
      "_id": null,
      "uniquePids": {
        "$addToSet": "$AllProds"
      }
    }
  }
])

Here is the mongo playground for your reference.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.