我目前有一个遵循如下格式的集合:
{ "_id": ObjectId(...),
"name" : "Name",
"red": 0,
"blue": 0,
"yellow": 1,
"green": 0,
...}
等等(一堆颜色)。我想做的是创建一个名为 colors
的新数组,其元素是值为 1 的那些颜色。
例如:
{ "_id": ObjectId(...),
"name" : "Name",
"colors": ["yellow"]
}
这是我可以在 Mongo shell 上做的事情吗?还是我应该在程序中做? 我很确定我可以使用 Python 来完成它,但是我在尝试直接在 shell 中进行操作时遇到了困难。如果可以在 shell 中完成,谁能指出正确的方向?
谢谢。
最佳答案
是的,它可以在 shell 中轻松完成,或者基本上按照适用于任何语言的示例进行操作。
这里的关键是查看“颜色”字段,然后构造一个更新语句,从文档中删除这些字段,同时测试它们是否有效以包含到数组中,然后当然添加以及文档更新:
var bulk = db.collection.initializeOrderedBulkOp(),
count = 0;
db.collection.find().forEach(function(doc) {
doc.colors = doc.colors || [];
var update = { "$unset": {}};
Object.keys(doc).filter(function(key) {
return !/^_id|name|colors/.test(key)
}).forEach(function(key) {
update.$unset[key] = "";
if ( doc[key] == 1)
doc.colors.push(key);
});
update["$addToSet"] = { "colors": { "$each": doc.colors } };
bulk.find({ "_id": doc._id }).updateOne(update);
count++;
if ( count % 1000 == 0 ) {
bulk.execute();
bulk = db.collection.initializeOrderedBulkOp()
}
});
if ( count % 1000 != 0 )
bulk.execute();
Bulk Operations使用意味着发送批量更新而不是每个文档一个请求和响应,因此这将比仅仅来回发布单一更新处理得更快。
这里主要的运算符是$unset
删除现有字段和 $addToSet
添加新的评估数组。两者都是通过循环文档中构成可能颜色的键并使用正则表达式过滤器排除您不想修改的其他键来构建的。
同时使用 $addToSet
和这一行:
doc.colors = doc.colors || [];
目的是确保如果任何文档已经部分转换或以其他方式被已经开始存储正确数组的代码更改触及,那么这些不会受到更新过程的不利影响或覆盖。
关于MongoDB:列表中的几个字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32802874/