在我的网页抓取项目中,我需要将前一天的数据从mongo_collection
移到mongo_his_collection
我正在使用此查询来移动数据
for record in collection.find():
his_collection.insert(record)
collection.remove()
它工作正常,但有时当MongoDB collection
包含 10k行
建议我一些优化的查询,它将占用更少的资源并执行相同的任务
答案 0 :(得分:2)
您可以使用MapReduce作业。
MapReduce允许您指定用于存储结果的收集。
当你有一个map函数发出每个文件时,它自己的_id作为键,而reduce函数返回值数组的第一个(在这种情况下只是因为_id是唯一的)条目,MapReduce本质上是一个副本从源集合到集合的操作。
未经测试的代码:
db.runCommand(
{
mapReduce: "mongo_collection",
map: function(document) {
emit(document._id, document);
},
reduce: function(key, values) {
return values[0];
},
out: {
merge:"mongo_his_collection"
}
}
)
答案 1 :(得分:1)
如果您的收藏集都位于同一个数据库中,我相信您正在寻找renameCollection。
如果没有,你不幸的是必须使用有针对性的mongodump / mongorestore命令手动完成:
mongodump -d your_database -c mongo_collection
mongorestore -d your_database -c mongo_his_collection dump/your_database/mongo_collection.bson
请注意,我只是从头顶输入这两个命令而没有实际测试它们,因此请确保在生产中运行它们之前检查它们。
[编辑]:对不起,我刚才意识到这是你需要定期做的事情。在这种情况下,mongodump / mongorestore
可能不是最佳解决方案。
我认为你的解决方案没有任何问题 - 如果你编辑了你的问题来解释你的意思,那么它会有所帮助。
答案 2 :(得分:1)
查询中断是因为您没有限制find()。在服务器上创建游标时,mongod将尝试将整个结果集加载到内存中。如果您的收藏太大,这将导致问题和/或失败。
为避免这种情况,请使用跳过/限制循环。以下是Java中的一个示例:
long count = 0
while (true) {
MongoClient client = new MongoClient();
DBCursor = client.getDB("your_DB_name").getCollection("mongo_collection").find().sort(new BasicDBObject("$natural", 1)).skip(count).limit(100);
while (cursor.hasNext()) {
client.getDB("your_DB_name").getCollection("mongo_his_collection").insert(cursor.next());
count++;
}
}
这将有效,但您也可以通过批量处理来获得更好的性能。为此,从游标构建一个DBObjects数组,并使用一个插入一次性写入所有这些数组。
此外,如果在复制时更改了收藏集,则无法保证您将遍历所有文档,因为如果它们的大小增加,最终可能会被移动。
答案 3 :(得分:0)
您可以尝试mongodump& mongorestore
答案 4 :(得分:0)
您可以使用renameCollection
直接执行此操作。或者,如果在不同的mongods上,请使用cloneCollection
。
参考文献: