这是一个重要的问题,因为MongoDB无法索引空值(即不要查询空值,否则将等待很长时间),因此最好完全避免使用空值,并使用
setOnInsert
设置默认值。
以下是递归解决方案以删除空值:
function getNullKeysRecursively(doc, keyName, nullKeys)
{
for (var item_property in doc)
{
if (!doc.hasOwnProperty(item_property))
continue;
if (item_property === "_id")
continue;
var fullKeyName;
if (keyName)
fullKeyName = keyName + "." + item_property;
else
fullKeyName = item_property;
if (doc[item_property] === null || doc[item_property] === undefined)
nullKeys[fullKeyName] = 1;
else if (doc[item_property] instanceof Object || doc[item_property] instanceof Array)
getNullKeysRecursively(doc[item_property], fullKeyName, nullKeys);
}
}
function removeNulls(collectionName)
{
var coll = db.getCollection(collectionName);
var lastId = ObjectId("000000000000000000000000");
var LIMIT = 10000;
while (true)
{
var page = coll.find({ _id: { $gt: lastId } }).limit(LIMIT);
if (! page.hasNext())
break;
var arrBulkOps = [];
page.forEach(function(item_doc)
{
lastId = item_doc._id;
var nullKeys = {};
getNullKeysRecursively(item_doc, null, nullKeys);
if (Object.keys(nullKeys).length > 0)
arrBulkOps.push(
{ updateOne: {
"filter": { _id: item_doc._id },
"update": { $unset: nullKeys }
} }
);
});
coll.bulkWrite(arrBulkOps, { ordered: false } );
}
}
removeNulls('my_collection');
之前的文档:
{
"_id": ObjectId("5a53ed8f6f7c4d95579cb87c"),
"first_name": null,
"last_name": "smith",
"features": {
"first": {
"a": 1,
"b": 2,
"c": null
},
"second": null,
"third" : {},
"fourth" : []
},
"other": [
null,
123,
{
"a": 1,
"b": "hey",
"c": null
}
]
}
文档之后:
{
"_id" : ObjectId("5a53ed8f6f7c4d95579cb87c"),
"last_name" : "smith",
"features" : {
"first" : {
"a" : 1,
"b" : 2
}
},
"other" : [
null,
123,
{
"a" : 1,
"b" : "hey"
}
]
}
正如您所看到的,它会删除null
、undefined
、空对象和空数组。如果您需要更多/更少的限制,只需修改“NULL FIELDS - MODIFY THIS BLOCK TO ADD CONSTRAINTS”块即可。
欢迎编辑,特别是@stennie。