Search code examples
c#mongodbmongodb-.net-driver

How do I project to remove attributes from an array that don't match a filter


I'd like to filter for documents that match a filter, and then project to remove array values that don't match requirements. In this example I need pickme1 and pickme2 to both be true. Searching for attr $eq value

{
  "_id" : ObjectId("qewrjkl"),
  "attr" : "value",
  "aray1" [
    {
      "pickme1" : true,
      "data1" : "jklsdjk",
      "aray2" [
        {     
           "pickme2" : true,
           "data2" : "treasure1"
        },
        {     
           "pickme2" : false,
           "data2" : "trash1"
        },
      ]
    },
    {
      "pickme1" : false
      "data1" : "jklsdjk",
      "aray2" [
        {     
           "pickme2" : true,
           "data2" : "treasure2"
        },
        {     
           "pickme2" : false,
           "data2" : "trash2"
        },
      ]
    },
  ]
}

should yield

{
  "_id" : ObjectId("qewrjkl"),
  "attr" : "value",
  "results" [
    {"data2" : "treasure1"}
  ]
}

I started with collection.Aggregate().Match(filter).Lookup() figuring I could fill the array with the lookup, and realized that was going nowhere. I don't have any ideas at this point. Does anyone have any ideas? If nothing is found inside the array then the document(s) should have an empty array.


Solution

  • The aggregation

    db.collection.aggregate([
      {
        $addFields: {
          aray1: {
            $filter: {
              input: {
                $map: {
                  input: "$aray1",
                  as: "a1",
                  in: {
                    aray2: {
                      $filter: {
                        input: "$$a1.aray2",
                        as: "ia2",
                        cond: {
                          $eq: [
                            "$$ia2.pickme2",
                            true
                          ]
                        }
                      }
                    },
                    pickme1: "$$a1.pickme1",
                    data1: "$$a1.data1"
                  }
                }
              },
              as: "oa1",
              cond: {
                $eq: [
                  "$$oa1.pickme1",
                  true
                ]
              }
            }
          }
        }
      },
      {
        "$project": {
          result: "$aray1.aray2",
          attr: 1
        }
      },
      {
        "$project": {
          "result.data2": 1,
          attr: 1
        }
      }
    ])
    

    Working Mongo playground