我一直在使用Mongoose将大量数据插入到mongodb数据库中。我注意到默认情况下,Mongoose将_id字段添加到所有子文档中,留下我看起来像这样的文档(为了简洁,我删除了很多字段 - 我还将每个数组缩小为一个条目,它们通常有更多)
{
"start_time" : ISODate("2013-04-05T02:30:28Z"),
"match_id" : 165816931,
"players" : [
{
"account_id" : 4294967295,
"_id" : ObjectId("51daffdaa78cee5c36e29fba"),
"additional_units" : [ ],
"ability_upgrades" : [
{
"ability" : 5155,
"time" : 141,
"level" : 1,
"_id" : ObjectId("51daffdaa78cee5c36e29fca")
},
]
},
],
"_id" : ObjectId("51daffdca78cee5c36e2a02e")
}
我已经找到了如何防止Mongoose默认添加这些(http://mongoosejs.com/docs/guide.html,请参阅选项:id),但是我现在在所有子文档上都有9500万条带有这些无关的_id字段的记录。我有兴趣找到删除所有这些字段的最佳方法(将_id保留在顶级文档中)。我最初的想法是在每个对象上使用一堆for...in
循环,但这看起来非常低效。
答案 0 :(得分:2)
可以使用更新操作删除players._id
,如下所示:
db.collection.update({'players._id': {$exists : 1}}, { $unset : { 'players.$._id' : 1 } }, false, true)
但是,not possible在嵌套数组中使用positional operator。因此,一种解决方案是直接在我们的数据库上运行脚本:
var cursor = db.collection.find({'players.ability_upgrades._id': {$exists : 1}});
cursor.forEach(function(doc) {
for (var i = 0; i < doc.players.length; i++) {
var player = doc.players[i];
delete player['_id'];
for (var j = 0; j < player.ability_upgrades.length; j++) {
delete player.ability_upgrades[j]['_id'];
}
}
db.collection.save(doc);
});
将脚本保存到文件并使用文件作为参数调用mongo:
> mongo remove_oid.js --shell
答案 1 :(得分:2)
鉴于Derick的回答,我创建了一个函数来执行此操作:
var deleteIdFromSubdocs = function (obj, isRoot) {
for (var key in obj) {
if (isRoot == false && key == "_id") {
delete obj[key];
} else if (typeof obj[key] == "object") {
deleteIdFromSubdocs(obj[key], false);
}
}
return obj;
使用以下命令对测试集合运行:
db.testobjects.find().forEach(function (x){ y = deleteIdFromSubdocs(x, true); db.testobjects.save(y); } )
这似乎适用于我的测试集。我想看看是否有任何人对我如何在与9500万份文件集合进行比较之前更好/相关的风险有任何意见。
答案 2 :(得分:0)
唯一的解决方案是逐个执行此操作,完全采用您所描述的for...in
循环。
答案 3 :(得分:0)
只是另一个版本,请使用AngularJS和MongoDB进行尝试; - )
function removeIds (obj, isRoot) {
for (var key in obj._doc) {
if (isRoot == false && key == "_id") {
delete obj._doc._id;
} else if ((Object.prototype.toString.call( obj[key] ) === '[object Array]' )) {
for (var i=0; i<obj[key].length; i++)
removeIds(obj[key][i], false);
}
}
return obj;
}
<强>用法:强>
var newObj = removeIds(oldObj, true);
delete newObj._id;