dynamic field name in `pipeline` of lookup where the value of the dynamic field name is determined by a variable set in `let`

133 Views Asked by At
user schema:

{
  _id: "OjectId",
}
interaction schema:

{
    blocker_id: user_id_x
    blocked:  { 
        user_id_y: true, 
        user_id_z: true,
        etc...
     }
}
                db.user.aggregate([{
                  $lookup: {
                    from: "interaction",
                    as: "remove",
                    let: { tar_id: "$_id" },
                    pipeline: [
                      {
                        $match: {
                          [`blocked[$$tar_id]`]: true,
                        },
                      },
                      {
                        $limit: 1,
                      },
                      {
                        $project: {
                          _id: 0,
                          remove: "true",
                        },
                      },
                    ],
                  },
                }]}

Notice the line:

  [`blocked[$$tar_id]`]: true,

Does the above lookup work? If not, how can I get it to work as intended?

The reason for this schema design is because looking up the value of an object’s property is O(1), while looking up an element of an array is O(N). Huge difference. Any solution must maintain the O(1) time complexity of the query.

EDIT:

tested. It does not work. The problem remains, how do I get to work as desired?

1

There are 1 best solutions below

3
On

One option is:

db.user.aggregate([
  {$lookup: {
      from: "interaction",
      as: "remove",
      let: {tar_id: {$toString: "$_id"}},
      pipeline: [
        {$match: {
            $expr: {
              $gt: [
                {$size: {
                    $filter: {
                      input: {$objectToArray: "$blocked"},
                      cond: {$eq: ["$$tar_id", "$$this.k"]}
                    }
                }},
                0
              ]
            }
        }},
        {$limit: 1},
        {$project: {_id: 0, remove: "true"}}
      ]
    }
  }
])

See how it works on the playground example