有没有办法用MongoDB驱动程序填充批量插入的向量,然后在不进行克隆的情况下再次使用它?

有没有办法用MongoDB驱动程序填充批量插入的向量,然后在不进行克隆的情况下再次使用它?,mongodb,rust,bulkinsert,Mongodb,Rust,Bulkinsert,我想使用将文档批量插入到集合中。我有一个bulk向量,当达到给定大小时,我填充并刷新它 我的问题是,我必须.clone()将向量提供给驱动程序的APIbulk\u write() 如果不克隆,则会出现E0382:use after move错误,并且API似乎不接受引用(E0308:expected structstd::vec::vec,find reference) 我是新手。有没有办法不用克隆这个大结构就可以做到这一点?(结构在我的示例中不大,但在我的实际代码中) 这是我的密码: // C

我想使用将文档批量插入到集合中。我有一个
bulk
向量,当达到给定大小时,我填充并刷新它

我的问题是,我必须
.clone()
将向量提供给驱动程序的API
bulk\u write()

如果不克隆,则会出现E0382:use after move错误,并且API似乎不接受引用(E0308:expected struct
std::vec::vec
,find reference

我是新手。有没有办法不用克隆这个大结构就可以做到这一点?(结构在我的示例中不大,但在我的实际代码中)

这是我的密码:

// Cargo.toml extract:
//
// [dependencies]
// bson = "0.10"
// mongodb = "0.3.7"

#[macro_use(bson, doc)] extern crate bson;
extern crate mongodb;
use mongodb::coll::options::WriteModel;
use mongodb::{Client, ThreadedClient};
use mongodb::db::ThreadedDatabase;

fn main() {

    // Connect to MongoDB and select collection
    let client = Client::connect("localhost", 27017).ok().expect("Failed to initialize client.");
    let coll = client.db("test").collection("mycol");

    // Make the bulk vector
    let mut bulk = Vec::new();
    for i in 0..1000 {

        // Append a item to the bulk
        bulk.push(WriteModel::UpdateOne { filter: doc!{"_id": i},
                                          update: doc!{"$set" => {"hello" => "world"}},
                                          upsert: Some(true) });

        // Each 11 items, flush bulk
        if bulk.len() > 10 {
            println!("Upsert {} docs into collection...",bulk.len());

            // `bulk` have to be cloned here
            let result = coll.bulk_write(bulk.clone(), true); // Unoptimal: bulk cloned
            //let result = coll.bulk_write(bulk, true); // E0382: use after move
            //let result = coll.bulk_write(&bulk, true); // E0308: expected struct `std::vec::Vec`, found reference 

            // Check result
            match result.bulk_write_exception {
                Some(exception) => {
                    if exception.message.len()>0 {
                        println!("ERROR: {}",exception.message);
                    }
                }
                None => ()
            }
            bulk.clear();
        }
    }

    // Final flush
    if bulk.len() > 0 {
        println!("Upsert {} docs into collection...",bulk.len());
        let result = coll.bulk_write(bulk.clone(), true);
        match result.bulk_write_exception {
            Some(exception) => {
                if exception.message.len()>0 {
                    println!("ERROR: {}",exception.message);
                }
            }
            None => ()
        }
    }
}

多亏了kazemakase,我可以通过创建一个新的空向量,交换两个向量并发送完整的向量来解决我自己的问题。以下是新的工作代码:

// Cargo.toml extract:
//
// [dependencies]
// bson = "0.10"
// mongodb = "0.3.7"

#[macro_use(bson, doc)] extern crate bson;
extern crate mongodb;
use mongodb::coll::options::WriteModel;
use mongodb::{Client, ThreadedClient};
use mongodb::db::ThreadedDatabase;
use std::mem;

fn main() {

    // Connect to MongoDB and select collection
    let client = Client::connect("localhost", 27017).ok().expect("Failed to initialize client.");
    let coll = client.db("test").collection("mycol");

    // Make the bulk vector
    let mut bulk = Vec::new();
    for i in 0..1000 {

        // Append a item to the bulk
        bulk.push(WriteModel::UpdateOne { filter: doc!{"_id": i},
                                          update: doc!{"$set" => {"hello" => "world"}},
                                          upsert: Some(true) });

        // Each 11 items, flush bulk
        if bulk.len() > 10 {
            println!("Upsert {} docs into collection...",bulk.len());

            let mut bulk2 = Vec::new(); // create new empty bulk
            mem::swap(&mut bulk, &mut bulk2); // bulk <-> bulk2
            let result = coll.bulk_write(bulk2, true);  // send full bulk

            //let result = coll.bulk_write(bulk.clone(), true); // Unoptimal: bulk cloned
            //let result = coll.bulk_write(bulk, true); // E0382: use after move
            //let result = coll.bulk_write(&bulk, true); // E0308: expected struct `std::vec::Vec`, found reference 

            // Check result
            match result.bulk_write_exception {
                Some(exception) => {
                    if exception.message.len()>0 {
                        println!("ERROR: {}",exception.message);
                    }
                }
                None => ()
            }
            //bulk.clear(); // bulk is now a new empty bulk, clear is unecessary
        } // Compiler will drop bulk2 (the full bulk) at this point
    }

    // Final flush
    if bulk.len() > 0 {
        println!("Upsert {} docs into collection...",bulk.len());
        let result = coll.bulk_write(bulk, true); // No clone nor swap needed here
        match result.bulk_write_exception {
            Some(exception) => {
                if exception.message.len()>0 {
                    println!("ERROR: {}",exception.message);
                }
            }
            None => ()
        }
    }
}
//Cargo.toml解压:
//
//[依赖关系]
//bson=“0.10”
//mongodb=“0.3.7”
#[宏_使用(bson,doc)]外部板条箱bson;
外部板条箱mongodb;
使用mongodb::coll::options::WriteModel;
使用mongodb::{Client,ThreadedClient};
使用mongodb::db::ThreadedDatabase;
使用std::mem;
fn main(){
//连接到MongoDB并选择collection
让client=client::connect(“localhost”,27017).ok().expect(“初始化客户端失败”);
设coll=client.db(“test”).collection(“mycol”);
//生成体向量
让mut bulk=Vec::new();
对于0..1000中的i{
//将项目追加到批量中
bulk.push(WriteModel::UpdateOne{filter:doc!{“\u id”:i},
更新:doc!{“$set”=>{“hello”=>“world”},
upsert:Some(true)});
//每件11件,齐平散装
如果bulk.len()大于10{
println!(“将{}个文档插入集合…”,bulk.len();
让mut bulk2=Vec::new();//创建新的空批量
mem::swap(&mut bulk,&mut bulk2);//bulk2
让result=coll.bulk_write(bulk2,true);//发送全批量
//让result=coll.bulk_write(bulk.clone(),true);//异常:批量克隆
//让result=coll.bulk_write(bulk,true);//E0382:移动后使用
//let result=coll.bulk_write(&bulk,true);//E0308:应为结构'std::vec::vec',找到引用
//检查结果
匹配结果。大容量\u写入\u异常{
一些(例外)=>{
如果exception.message.len()大于0{
println!(“错误:{}”,exception.message);
}
}
无=>()
}
//bulk.clear();//bulk现在是一个新的空bulk,clear是不必要的
}//此时编译器将删除bulk2(完整的bulk)
}
//最终冲洗
如果bulk.len()大于0{
println!(“将{}个文档插入集合…”,bulk.len();
让result=coll.bulk_write(bulk,true);//此处不需要克隆或交换
匹配结果。大容量\u写入\u异常{
一些(例外)=>{
如果exception.message.len()大于0{
println!(“错误:{}”,exception.message);
}
}
无=>()
}
}
}

正如@kazemakase在评论中指出的那样,它是
mem::replace()
。但是,在本例中,我们需要挂起
bulk
的原因是最后一种情况,即
bulk.len(){“hello”=>“world”},
upsert:Some(true)})
.收集();
普林顿!(“向集合中插入{}个文档…”,bulk.len();
让结果=coll.bulk\u write(bulk);
如果让某些(异常)=result.bulk\u写入异常{
如果exception.message.len()大于0{
println!(“错误:{}”,exception.message);
}
}
}

这里的主要变化是使用
slice::chunks()
,而不是在主迭代循环中手动将块构建到
bulk
。另一个好处是,这样做可以消除重复的错误处理,并且更加惯用。

解决了您的问题吗?如果没有,你能解释一下原因吗?谢谢,
mem::swap()
解决了我的问题。也谢谢!slice::chunk()[解决方案是第一个collect(),例如,如果要插入的文档是通过解析一个3Gb文件生成的,那么在开始插入之前获取所有文档可能会耗费大量内存。这就是为什么我更喜欢Shepmaster上面提出的itertools::chunks(),因为它适用于迭代器而不是切片。
// Connect to MongoDB and select collection
let client = Client::connect("localhost", 27017).ok().expect("Failed to initialize client.");
let coll = client.db("test").collection("mycol");

let ranges: Vec<_> = (0..1000).into_iter().collect();
for range in ranges[..].chunks(11) {
    let bulk: Vec<_> = 
        range.map(|i| WriteModel::UpdateOne { filter: doc!{"_id": i},
                                              update: doc!{"$set" => {"hello" => "world"}},
                                              upsert: Some(true) })
        .collect();

    println!("Upsert {} docs into collection...", bulk.len());

    let result = coll.bulk_write(bulk);
    if let Some(exception) = result.bulk_write_exception {
        if exception.message.len() > 0 {
            println!("ERROR: {}", exception.message);
        }
    }
}