2015-09-26 46 views
2

我现在有下面这样的格式的集合:MongoDB的:几个字段列表

{ "_id": ObjectId(...), 
    "name" : "Name", 
    "red": 0, 
    "blue": 0, 
    "yellow": 1, 
    "green": 0, 
    ...} 

等(一堆颜色)。我想这样做是为了创建一个名为colors新的数组,其元素是那些有1

的值。例如颜色:

{ "_id": ObjectId(...), 
    "name" : "Name", 
    "colors": ["yellow"] 
} 

这是不是我可以在做蒙戈贝壳?或者我应该在一个程序中做? 我很确定我可以用Python来完成,但是我很难直接在shell中执行它。如果它可以在shell中完成,任何人都可以指向正确的方向吗?

谢谢。

回答

1

是的,它可以很容易地在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 || []; 

享有作为确信,如果任何文件已经部分转化或通过已经开始存储正确的数组码变化,那么这些否则触摸的目的不会受到更新过程的不利影响或覆盖。

1

tl;dr, spoiler

MongoDB的外壳可以访问自己的对象的某些JavaScript的方法等。您可以使用db.yourCollectionName.find()查询您的收藏集,这将返回一个光标(cursor methods)。然后迭代获取每个文档,遍历这些键,有条件地过滤掉诸如_idname之类的键,然后检查值是否为1,将该键存储在集合中的某处。

一旦这样做,你可能想通过_id使用db.yourCollectionName.update()db.yourCollectionName.findAndModify()来查找记录,并使用$set添加一个新的领域,并设置其值为键的集合。