首页 > 解决方案 > mongodb 中多个字段的 $unset

问题描述

假设我在 mongoDB 中有一个集合,如下所示 -

{
name : "Abhishek",
Roll_no : null,
hobby : stackoverflow
},
{
name : null,
Roll_no : 1,
hobby : null
}

现在我想删除我的文档中字段值为空的字段。我知道我可以通过$unset以下方式做到这一点 -

db.collection.updateMany({name: null}, { $unset : { name : 1 }});

我们可以用同样的方式来处理爱好和姓名字段。

但我想知道我是否可以只使用一个查询来执行相同的删除操作?我想知道我是否可以使用$or或其他东西来达到相同的效果,但在一个命令中。

有任何想法吗?

标签: databasemongodbmongoosemongodb-query

解决方案


在 MongoDB 版本 >= 上3.2

您可以利用.bulkWrite()

let bulkArr = [
  {
    updateMany: {
      filter: { name: null },
      update: { $unset: { name: 1 } }
    }
  },
  {
    updateMany: {
      filter: { Roll_no: null },
      update: { $unset: { Roll_no: 1 } }
    }
  },
  {
    updateMany: {
      filter: { hobby: null },
      update: { $unset: { hobby: 1 } }
    }
  },
];

/** All filter conditions will be executed on all docs
 *  but respective update operation will only be executed if respective filter matches (kind of individual ops) */
db.collection.bulkWrite(bulkArr);

参考: 批量写入

在 MongoDB 版本 >= 上4.2

由于您想删除具有值的多个字段(其中字段名称无法列出或未知)null,请尝试以下查询:

db.collection.update(
  {}, // Try to use a filter if possible
  [
    /** 
     * using project as first stage in aggregation-pipeline
     * Iterate on keys/fields of document & remove fields where their value is 'null'
     */
    {
      $project: {
        doc: {
          $arrayToObject: { $filter: { input: { $objectToArray: "$$ROOT" }, cond: { $ne: ["$$this.v", null] } } }
        }
      }
    },
    /** Replace 'doc' object as root of document */
    {
      $replaceRoot: { newRoot: "$doc" }
    }
  ],
  { multi: true }
);

测试: mongoplayground

参考 : update-with-an-aggregation-pipeline ,聚合管道

笔记 :

我相信这将是一次性操作,将来您可以使用Joinpm 包或 mongoose 模式验证器来限制写入null作为字段值。如果您可以列出您的字段名称,好像没有太多加上数据集大小太高,那么请尝试$$REMOVE按照“@thammada”的建议使用聚合。

到目前为止,.updateMany()许多客户端甚至很少的 mongo shell 版本都不支持聚合管道 in ——当时我给他们的票通过 using 得到了解决.update(),如果它不起作用,那么尝试使用update + { multi : true }.


推荐阅读