我的文档中有一个字段,以其时间戳命名,如下所示:
{
_id: ObjectId("53f2b954b55e91756c81d3a5"),
domain: "example.com",
"2014-08-07 01:25:08": {
A: [
"123.123.123.123"
],
NS: [
"ns1.example.com.",
"ns2.example.com."
]
}
}
这对查询来说非常不切实际,因为每个文档都有不同的时间戳。 因此,我想将所有文档的此字段重命名为固定名称。 但是,我需要能够使用正则表达式匹配字段名称,因为它们都是不同的。
我尝试过这样做,但这是非法查询。
db['my_collection'].update({}, {$rename:{ /2014.*/ :"201408"}}, false, true);
有人有解决此问题的方法吗?
基于NEIL LUNN的答案:
conn = new Mongo();
db = conn.getDB("my_db");
var bulk = db['my_coll'].initializeOrderedBulkOp();
var counter = 0;
db['my_coll'].find().forEach(function(doc) {
for (var k in doc) {
if (k.match(/^2014.*/) ) {
print("replacing " + k)
var unset = {};
unset[k] = 1;
bulk.find({ "_id": doc._id }).updateOne({ "$unset": unset, "$set": { WK1: doc[k]} });
counter++;
}
}
if ( counter % 1000 == 0 ) {
bulk.execute();
bulk = db['my_coll'].initializeOrderedBulkOp();
}
});
if ( counter % 1000 != 0 )
bulk.execute();
答案 0 :(得分:3)
这不是mapReduce操作,除非您想要一个仅包含从mapReduce输出生成的_id
和value
字段的新集合,就像:
"_id": ObjectId("53f2b954b55e91756c81d3a5"),
"value": {
"domain": "example.com",
...
}
}
充其量只是对您的收藏进行“服务器端”修改,但当然不是您想要的结构。
虽然有多种方法可以执行服务器中的所有代码,但请不要尝试这样做,除非您真的在某个地方。无论如何,这些方式通常不能很好地与分片一起使用,这通常是人们“真正在某个地方”的记录大小。
当您想要更改内容并批量执行时,通常必须“循环”收集结果并处理更新,同时可以访问当前文档信息。也就是说,如果您的“更新”是“基于”已包含在文档的字段或结构中的信息。
因此没有“正则表达式替换”操作可用,并且当然没有一个用于重命名字段。因此,让我们使用bulk operations循环,以“最安全”的方式执行此操作,而无需在服务器上运行所有代码。
var bulk = db.collection.initializeOrderedBulkOp();
var counter = 0;
db.collection.find().forEach(function(doc) {
for ( var k in doc ) {
if ( doc[k].match(/^2014.*/) ) {
var update = {};
update["$unset"][k] = 1;
update["$set"][ k.replace(/(\d+)-(\d+)-(\d+).+/,"$1$2$3") ] = doc[k];
bulk.find({ "_id": doc._id }).updateOne(update);
counter++;
}
}
if ( counter % 1000 == 0 ) {
bulk.execute();
bulk = db.collection.initializeOrderedBulkOp();
}
});
if ( counter % 1000 != 0 )
bulk.execute();
所以主要的事情是$unset
运算符删除现有字段,$set
运算符在文档中创建新字段。您需要文档内容来检查并使用“字段名称”和“值”,因此循环,因为没有其他方法。
如果服务器上没有MongoDB 2.6或更高版本,则循环概念仍然没有立即的性能优势。您可以查看.eval()
之类的内容以便在服务器上进行处理,但正如文档所示,我们不建议这样做。如果必须,请谨慎使用。
答案 1 :(得分:0)
正如您已经认识到的那样,对于MongoDB查询语言,value-key确实非常糟糕。很糟糕,你想做的事情都不起作用。
但你可以用MapReduce做到这一点。 map
和reduce
函数不会执行任何操作,但finalize函数会在Javascript中进行转换。
或者您可以使用您的编程语言编写一个小程序,从该集合中读取所有文档,进行更改,然后使用collection.save
将其写回。