mongodb 中多个字段的 $unset
Posted
技术标签:
【中文标题】mongodb 中多个字段的 $unset【英文标题】:$unset on multiple fields in mongodb 【发布时间】:2020-09-23 21:28:30 【问题描述】:假设我在 mongoDB 中有一个集合,如下所示 -
name : "Abhishek",
Roll_no : null,
hobby : ***
,
name : null,
Roll_no : 1,
hobby : null
现在我想删除我的文档中字段值为空的字段。我知道我可以通过以下方式使用$unset
来做到这一点-
db.collection.updateMany(name: null, $unset : name : 1 );
我们可以用同样的方式来处理爱好和姓名字段。
但我想知道是否可以只使用一个查询来执行相同的删除操作?我想知道是否可以使用$or
或其他东西来实现相同的效果,但只需一个命令。
有什么想法吗?
【问题讨论】:
你的数据库版本是多少? 4.0.15 但考虑我可以将其更新到最新版本。 好的,如果你可以升级到4.2
,你会有更好的选择来处理它..
【参考方案1】:
在 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);
参考: bulkwrite
在 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 , aggregation-pipeline
注意:
我相信这将是一次性操作,将来您可以使用Joi
npm 包或猫鼬模式验证器来限制将null
写入字段值。如果您可以列出您的字段名称,就好像没有太多加上数据集大小太高,那么请尝试使用 $$REMOVE
的聚合,正如“@thammada”所建议的那样。
到目前为止,.updateMany()
中的聚合管道不受许多客户端的支持,即使是少数 mongo shell 版本 - 当时我的票通过使用 .update()
解决了,如果它不起作用,请尝试使用update + multi : true
.
【讨论】:
我很好奇,.updateMany()
中的聚合管道是否也受到常规聚合管道的内存限制,是否有类似的方法来允许磁盘使用?
@thammada : 不确定,但总的来说,我相信.update()
中使用的阶段可能不是问题,因为大多数时候你在尝试积累文档,例如使用$group
或$sort
进行计算。【参考方案2】:
使用 MongoDB v4.2,您可以使用 Updates with Aggregation Pipeline 以及 $$REMOVE
系统变量
db.collection.updateMany(
$or: [
name: null
,
Roll_no: null
,
hobby: null
]
, [
$set:
name: $ifNull: ["$name", "$$REMOVE"]
Roll_no: $ifNull: ["$Roll_no", "$$REMOVE"] ,
hobby: $ifNull: ["$hobby", "$$REMOVE"]
]
【讨论】:
以上是关于mongodb 中多个字段的 $unset的主要内容,如果未能解决你的问题,请参考以下文章
MongoDb:如何根据每个字段的值更新多个文档中的字段值?