MongoDB:列表中的几个字段

时间:2015-09-26 23:00:38

标签: mongodb mongodb-query

我目前有一个遵循以下格式的集合:

{ "_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中完成,那么有人能指出我正确的方向吗?

感谢。

2 个答案:

答案 0 :(得分:1)

tl;dr, spoiler

Mongodb的shell可以在其对象上访问一些类似javascript的方法。您可以使用db.yourCollectionName.find()查询您的收藏集,该cursor methods将返回一个游标(db.yourCollectionName.update())。然后迭代以获取每个文档,遍历键,有条件地过滤掉_idname等键,然后检查值是否为1,将该键存储在某个位置集合。

完成后,您可能希望使用db.yourCollectionName.findAndModify()Bootsnipp_id查找记录,并使用$set添加新字段并设置它对钥匙集合的价值。

答案 1 :(得分:1)

是的,它可以在shell中轻松完成,或者基本上遵循适用于任何语言的示例。

这里的关键是查看“colors”字段然后构造一个更新语句,该语句在测试它们时从文档中删除这些字段以查看它们是否有效包含在数组中,然后当然添加到文档更新:

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 || [];

目的是确保如果任何文档已经被已经开始存储正确数组的代码更改部分转换或以其他方式触及,则这些不会受到更新过程的不利影响或覆盖。