Search code examples
mongodbmongodb-querypymongo

How to unset fields based on the fields' name with a "less than" condition?


I am trying to unset certain fields based on the name of the field (the key).

Say I have something like this:

{
    5: "cool",
    93: "cool",
    30: "cool",
    56: "cool"
}

How would I unset all fields with a value below, say, 40.

So the result should be:

{
    5: "cool",
    30: "cool"
}

I tried using the less than command on the whole field or using the positional operator but both of those failed.

collection.update_one(
        {"_id": id},
        {"$unset": {"blacklist.$": {"$lt": 40}}}
    )

I couldn't find anything online or on the docs so I am hoping to find some help here,

Thanks!


Solution

  • You can't really use $unset like this, we can still achieve this using pipelined updates - with slightly more complicated syntax.

    Our approach will be to turn our root object to an array using $objectToArray, iterate over it and filter all numeric keys under a certain threshold. then finally convert back to an object and update our document, like so:

    db.collection.update({},
    [
      {
        $replaceRoot: {
          newRoot: {
            $arrayToObject: {
              $filter: {
                input: {
                  $objectToArray: "$$ROOT"
                },
                cond: {
                  $cond: [
                    {
                      $regexMatch: {
                        input: "$$this.k",
                        regex: "^[0-9]+$"
                      }
                    },
                    {
                      $lt: [
                        {
                          $toInt: "$$this.k"
                        },
                        40
                      ]
                    },
                    true
                  ]
                }
              }
            }
          }
        }
      }
    ])
    

    Mongo Playground