如何根据具有 "less than" 条件的字段名称取消设置字段?

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

我正在尝试根据字段名称(键)取消设置某些字段。

假设我有这样的东西:

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

我如何取消设置值低于 40 的所有字段。

所以结果应该是:

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

我尝试在整个字段上使用小于命令或使用位置运算符,但都失败了。

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

我在网上或文档上找不到任何东西,所以我希望能在这里找到一些帮助,

谢谢!

您不能像这样真正使用 $unset,我们仍然可以使用流水线更新来实现此目的 - 语法稍微复杂一些。

我们的方法是使用 $objectToArray 将根对象转换为数组,对其进行迭代并过滤特定阈值以下的所有数字键。然后最终转换回对象并更新我们的文档,如下所示:

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

查询

  • 进入[]$$ROOT
  • 将键过滤为 "_id"< 40
  • 返回对象并
  • 替换根

*这会删除所有字段 >=40 ,如果不需要这个

可以更改最后一个 $lt

*toms 答案有效且更通用,如果你有混合键,有些是数字,有些不是使用 toms 方式(这稍微简单但假设所有字段都是数字,除了“_id”)

Test code here

aggregate(
[{"$replaceRoot":
  {"newRoot":
   {"$arrayToObject":
    [{"$filter":
      {"input":{"$objectToArray":"$$ROOT"},
       "cond":
       {"$or":
        [{"$eq":["$$this.k", "_id"]},
         {"$lt":[{"$toInt":"$$this.k"}, 40]}]}}}]}}}])