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

标签 mongodb rust bulkinsert

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

我的问题是,在将向量提供给驱动程序的 API bulk_write() 时,我必须 .clone() 向量。

如果我不克隆,我会遇到一个E0382: use after move 错误,似乎 API 不接受引用 ( em>E0308: 预期结构 std::vec::Vec,找到引用)。

我是 Rust 新手。有没有办法在不克隆这个大结构的情况下做到这一点? (结构在我的示例中并不大,但在我的实际代码中)

这是我的代码:

// 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 在评论中指出的那样,general solution to these kinds of problemsmem::replace() .然而,在这种情况下,我们需要卡在 bulk 上的原因适用于 bulk.len() <= 10 的最后一种情况.如果我们重构原始代码,我们可以完全避免Use after move错误:

// 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);
        }
    }
}

这里主要的变化是使用slice::chunks()而不是手动将 block 构建到 bulk 中在主迭代循环中。另一件好事是,这消除了重复的错误处理,并且更符合 Rust 的习惯。

关于mongodb - 有没有办法用 MongoDB 驱动程序填充批量插入的向量,然后在不克隆的情况下再次使用它?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50970102/

相关文章:

rust - 如何遍历切片的所有可能分区(非空子切片)?

mongodb - 在 MongoDB 控制台中按 _id 删除

java - 外部对象引用/多对象提交

macros - 如何在 Rust 中导入宏?

macros - 尝试!不会编译不匹配的类型

mysql - 在 SQL 文件中使用 IF 控制 INSERT 和 UPDATE 查询

javascript - 使用 MongoDB 聚合时出现错误, 'Can' t 从 BSON 类型 objectId 转换为 String'

Javascript JQuery - 使用带参数的事件创建动态按钮

android - 如何获取默认手机和 SIM 联系人的 ACCOUNT_TYPE 和 ACCOUNT_NAME?

MySQL:对于每个用户,使用该用户的 ID 将一行添加到另一个表中