mongodb将文档从一个集合移动到另一个集合
如何在MongoDB中将文档从一个集合移动到另一个集合??例如:我在集合A中有很多文档,我想将所有1个月前的文档移动到集合B(这些1个月前的文档不应该在集合A中) 使用聚合我们可以进行复制。但我正试图做的是移动文档。mongodb将文档从一个集合移动到另一个集合,mongodb,Mongodb,如何在MongoDB中将文档从一个集合移动到另一个集合??例如:我在集合A中有很多文档,我想将所有1个月前的文档移动到集合B(这些1个月前的文档不应该在集合A中) 使用聚合我们可以进行复制。但我正试图做的是移动文档。 可以使用什么方法移动文档?您可以使用范围查询从sourceCollection获取数据,并将光标数据保存在变量中,并在其上循环,然后插入到目标集合: var doc = db.sourceCollection.find({ "Timestamp":{
可以使用什么方法移动文档?您可以使用范围查询从sourceCollection获取数据,并将光标数据保存在变量中,并在其上循环,然后插入到目标集合:
var doc = db.sourceCollection.find({
"Timestamp":{
$gte:ISODate("2014-09-01T00:00:00Z"),
$lt:ISODate("2014-10-01T00:00:00Z")
}
});
doc.forEach(function(doc){
db.targetCollection.insert(doc);
})
db.source_collection.drop()
希望能有帮助 插入和删除:
var documentsToMove = db.collectionA.find({});
documentsToMove.forEach(function(doc) {
db.collectionB.insert(doc);
db.collectionA.remove(doc);
});
注意:对于大型集合或包含大型文档的集合,此方法可能会非常慢。从性能角度来看,最好使用一个命令删除大量文档(特别是如果您有查询部分的索引),而不是逐个删除它们 例如:
db.source.find({$gte: start, $lt: end}).forEach(function(doc){
db.target.insert(doc);
});
db.source.remove({$gte: start, $lt: end});
更新2 请不要再对这个答案投赞成票了。无论在哪一方面,写出来的都更好 更新 这是一种更安全的方法,应该用它来代替我的
如果我理解正确,并且您希望移动所有超过1个月的文档,并且您使用mongoDB 2.6,那么没有理由不使用批量操作,这是我所知道的执行多个操作的最有效方法:
> var bulkInsert = db.target.initializeUnorderedBulkOp()
> var bulkRemove = db.source.initializeUnorderedBulkOp()
> var date = new Date()
> date.setMonth(date.getMonth() -1)
> db.source.find({"yourDateField":{$lt: date}}).forEach(
function(doc){
bulkInsert.insert(doc);
bulkRemove.find({_id:doc._id}).removeOne();
}
)
> bulkInsert.execute()
> bulkRemove.execute()
这应该非常快,而且它的优点是,如果在大容量插入过程中出现错误,原始数据仍然存在
编辑 为了防止占用过多内存,您可以对处理的每个
x
文档执行批量操作:
> var bulkInsert = db.target.initializeUnorderedBulkOp()
> var bulkRemove = db.source.initializeUnorderedBulkOp()
> var x = 10000
> var counter = 0
> var date = new Date()
> date.setMonth(date.getMonth() -1)
> db.source.find({"yourDateField":{$lt: date}}).forEach(
function(doc){
bulkInsert.insert(doc);
bulkRemove.find({_id:doc._id}).removeOne();
counter ++
if( counter % x == 0){
bulkInsert.execute()
bulkRemove.execute()
bulkInsert = db.target.initializeUnorderedBulkOp()
bulkRemove = db.source.initializeUnorderedBulkOp()
}
}
)
> bulkInsert.execute()
> bulkRemove.execute()
这是对@Markus W Mahlberg的重述 回报恩惠-作为一种功能
function moveDocuments(sourceCollection,targetCollection,filter) {
var bulkInsert = targetCollection.initializeUnorderedBulkOp();
var bulkRemove = sourceCollection.initializeUnorderedBulkOp();
sourceCollection.find(filter)
.forEach(function(doc) {
bulkInsert.insert(doc);
bulkRemove.find({_id:doc._id}).removeOne();
}
)
bulkInsert.execute();
bulkRemove.execute();
}
示例使用
var x = {dsid:{$exists: true}};
moveDocuments(db.pictures,db.artifacts,x)
要将具有顶级元素dsid的所有文档从图片移动到MongoDB 3.0上的工件集合,可以使用具有以下语法的命令:
db.source_collection.copyTo("target_collection")
`function Recursion(){
Kitten.findOne().lean().exec(function(error, results){
if(!error){
var objectResponse = results;
var RequiredId = objectResponse._id;
delete objectResponse._id;
var swap = new Cat(objectResponse);
swap.save(function (err) {
if (err) {
return err;
}
else {
console.log("SUCCESSFULL");
Kitten.deleteOne({ _id: RequiredId }, function(err) {
if (!err) {
console.log('notification!');
}
else {
return err;
}
});
Recursion();
}
});
}
if (err) {
console.log("No object found");
// return err;
}
})
}`
然后可以使用命令删除旧集合:
var doc = db.sourceCollection.find({
"Timestamp":{
$gte:ISODate("2014-09-01T00:00:00Z"),
$lt:ISODate("2014-10-01T00:00:00Z")
}
});
doc.forEach(function(doc){
db.targetCollection.insert(doc);
})
db.source_collection.drop()
我很喜欢@markus-w-mahlberg的回复,但是有时候,我觉得有必要让人们的回答简单一点。因此,我有以下几个函数。您可以像他那样自然地使用批量操作符来包装这件事,但这段代码同样适用于新的和旧的Mongo系统
function parseNS(ns){
//Expects we are forcing people to not violate the rules and not doing "foodb.foocollection.month.day.year" if they do they need to use an array.
if (ns instanceof Array){
database = ns[0];
collection = ns[1];
}
else{
tNS = ns.split(".");
if (tNS.length > 2){
print('ERROR: NS had more than 1 period in it, please pass as an [ "dbname","coll.name.with.dots"] !');
return false;
}
database = tNS[0];
collection = tNS[1];
}
return {database: database,collection: collection};
}
function insertFromCollection( sourceNS, destNS, query, batchSize, pauseMS){
//Parse and check namespaces
srcNS = parseNS(sourceNS);
destNS = parseNS(destNS);
if ( srcNS == false || destNS == false){return false;}
batchBucket = new Array();
totalToProcess = db.getDB(srcNS.database).getCollection(srcNS.collection).find(query,{_id:1}).count();
currentCount = 0;
print("Processed "+currentCount+"/"+totalToProcess+"...");
db.getDB(srcNS.database).getCollection(srcNS.collection).find(query).addOption(DBQuery.Option.noTimeout).forEach(function(doc){
batchBucket.push(doc);
if ( batchBucket.length > batchSize){
db.getDB(destNS.database).getCollection(destNS.collection)insert(batchBucket);
currentCount += batchBucket.length;
batchBucket = [];
sleep (pauseMS);
print("Processed "+currentCount+"/"+totalToProcess+"...");
}
}
print("Completed");
}
/** Example Usage:
insertFromCollection("foo.bar","foo2.bar",{"type":"archive"},1000,20);
显然,您可以添加一个db.getSiblingDB(srcNS.database).getCollection(srcNS.collection).remove(query,true)
如果您希望在记录复制到新位置后也删除这些记录。代码可以像这样轻松构建,使其可重启。$out用于创建包含数据的新集合,所以使用$out
db.oldCollection.aggregate([{$out : "newCollection"}])
然后用滴水
db.oldCollection.drop()
我计划使用pymongo的bulkinsert和bulkdelete方法一次获取1000条记录 对于源和目标
//将其替换为mongodb对象创建逻辑
source\u db\u obj=db\u help.create\u db\u obj(source\u db,source\u col)
source\u bulk=source\u db\u obj.initialize\u ordered\u bulk\u op()
source\u bulk\u bak=source\u db\u obj.initialize\u ordered\u bulk\u op()
为目标
//将其替换为mogodb对象创建逻辑
target\u db\u obj=db\u help.create\u db\u obj(target\u db,target\u col)
target_bulk=target_db_obj.initialize_ordered_bulk_op()
target\u bulk\u bak=target\u db\u obj.initialize\u ordered\u bulk\u op()
`function Recursion(){
Kitten.findOne().lean().exec(function(error, results){
if(!error){
var objectResponse = results;
var RequiredId = objectResponse._id;
delete objectResponse._id;
var swap = new Cat(objectResponse);
swap.save(function (err) {
if (err) {
return err;
}
else {
console.log("SUCCESSFULL");
Kitten.deleteOne({ _id: RequiredId }, function(err) {
if (!err) {
console.log('notification!');
}
else {
return err;
}
});
Recursion();
}
});
}
if (err) {
console.log("No object found");
// return err;
}
})
}`
//将其替换为获取UTCtime的逻辑。
doc['archived_at']=db_help.getUTCTime()
目标\批量插入(文档)
源\批量删除(文档)
要在出现任何错误或异常时回滚,请创建目标\u bulk\u bak和源\u bulk\u bak操作
目标为bulk.find({'''u id':doc['''u id']})。删除一个()
来源\批量\包装插入(文件)
//删除额外的列
pop文件(“存档”,无)
def execute_bulk_insert_remove(source_bulk, target_bulk):
try:
target_bulk.execute()
source_bulk.execute()
except BulkWriteError as bwe:
raise Exception(
"could not archive document, reason: {}".format(bwe.details))
def archive_bulk_immediate(filter, source_db, source_col, target_db, target_col):
"""
filter: filter criteria for backup
source_db: source database name
source_col: source collection name
target_db: target database name
target_col: target collection name
"""
count = 0
bulk_count = 1000
source_db_obj = db_help.create_db_obj(source_db, source_col)
source_bulk = source_db_obj.initialize_ordered_bulk_op()
source_bulk_bak = source_db_obj.initialize_ordered_bulk_op()
target_db_obj = db_help.create_db_obj(target_db, target_col)
target_bulk = target_db_obj.initialize_ordered_bulk_op()
target_bulk_bak = target_db_obj.initialize_ordered_bulk_op()
source_find_results = source_db_obj.find(filter)
start = datetime.now()
for doc in source_find_results:
doc['archived_at'] = db_help.getUTCTime()
target_bulk.insert(doc)
source_bulk.find({'_id': doc['_id']}).remove_one()
target_bulk_bak.find({'_id': doc['_id']}).remove_one()
doc.pop('archieved_at', None)
source_bulk_bak.insert(doc)
count += 1
if count % 1000 == 0:
logger.info("count: {}".format(count))
try:
execute_bulk_insert_remove(source_bulk, target_bulk)
except BulkWriteError as bwe:
execute_bulk_insert_remove(source_bulk_bak, target_bulk_bak)
logger.info("Bulk Write Error: {}".format(bwe.details))
raise
source_bulk = source_db_obj.initialize_ordered_bulk_op()
source_bulk_bak = source_db_obj.initialize_ordered_bulk_op()
target_bulk = target_db_obj.initialize_ordered_bulk_op()
target_bulk_bak = target_db_obj.initialize_ordered_bulk_op()
end = datetime.now()
logger.info("archived {} documents to {} in ms.".format(
count, target_col, (end - start)))
如文所述,@markus-w-mahlberg(和@mark mullin精炼)的批量操作是高效的,但不安全。如果bulkInsert失败,bulkRemove仍将继续。为确保移动时不会丢失任何记录,请改用此选项:
函数插入批处理(集合、文档){
var bulkInsert=collection.initializeUnderedBulkop();
var insertedIds=[];
变量id;
文档.forEach(功能(文档){
id=单据编号;
//插入而不引发重复项的错误
bulkInsert.find({u id:id}).upsert().replaceOne(doc);
插入式推送(id);
});
bulkInsert.execute();
返回插入项;
}
函数deleteBatch(集合、文档){
var bulkRemove=collection.initia
db.getCollection("sourceColl").aggregate([
{ $merge: {
into: "targetColl",
on: "_id",
whenMatched: "fail",
whenNotMatched: "insert"
}}
]);
db.getCollection("sourceColl").deleteMany({})