Чтение файла .bson с помощью Rust

Меня очень заинтересовал двоичный файл .bson, созданный mongodump. Сначала я предположил, что это массив BSON Bson::Array(array_of_documents) Затем:

#Cargo.toml

[dependecies]
...
bson = "2.1.0"
//main.rs
fn main()
{
    let mut path=std::env::current_dir().unwrap();
    path.push("backup/transactions.bson");

    if path.exists() {
        match std::fs::File::open(&path)
        {
            Err(err)=>panic!("Failed to open '{}'",path.to_str().unwrap(),err),
            Ok(file)=>{
                if let Ok(bson_file)=bson::Bson::from_reader(&file) {
                    if let Some(bson_array)=bson_file.as_array() {
                        for bson_data in bson_array {
                            println!("BSON Data: {:?}",&bson_data);
                        }
                    }  else {
                        println!("Not an array");
                    }
                } else {
                    println!("Not a BSON file");
                }
            }
        }
    }
}

Тогда я побежал:

$ cargo run
...
Not an array

Очевидно, это файл BSON, а не массив! Что это было тогда? 🤔

Использование JavaScript и MongoDB
Использование JavaScript и MongoDB
Сегодня я собираюсь вкратце рассказать о прототипах в JavaScript, а также представить и объяснить вам работу с базой данных MongoDB.
0
0
88
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Потом я подумал... а что, если это будет Документ Bson::Document(bson_data)?

//main.rs
fn main()
{
    let mut path=std::env::current_dir().unwrap();
    path.push("backup/transactions.bson");

    if path.exists() {
        match std::fs::File::open(&path)
        {
            Err(err)=>panic!("Failed to open '{}'",path.to_str().unwrap(),err),
            Ok(mut file)=>{
                if let Ok(doc_data)=bson::Document::from_reader(&mut file) {
                   //Print all keys of the document
                   println!("Document keys: {:?}",doc_data.keys().map(|x| x.as_str()).collect::<Vec<&str>>());
                } else {
                   println!("Not a document");
                }
            }
        }
    }
}
$ cargo run
...
["_id","code","type","customerName","items","createdAt"]

Эти ключи — данные моей транзакции! 😮 Но он извлекает только один документ и печатает все ключи документа. Где остальные документы? У меня есть более 50 документов, сохраненных в файле .bson. Затем я кое-что заподозрил, а что, если... файл .bson состоит из нескольких документов, расположенных рядом друг с другом.

//main.rs
fn main()
{
    let mut path=std::env::current_dir().unwrap();
    path.push("backup/transactions.bson");

    if path.exists() {
        match std::fs::File::open(&path)
        {
            Err(err)=>panic!("Failed to open '{}'",path.to_str().unwrap(),err),
            Ok(mut file)=>{
                //Read file size
                let n=file.seek(std::io::SeekFrom::End(0)).unwrap_or(0);

                //Put file pointer at the beginning of file
                if file.seek(std::io::SeekFrom::Start(0)).is_ok() {
                    //Hold the number of retrieved documents
                    let mut i=0_u16;

                    //Read only 50 documents or end of file has been reached
                    while i < 50 && file.stream_position().unwrap_or(0) < n {
                       if let Ok(doc_data) = bson::Document::from_reader(&mut file) {
                           println!("Document: {}. {:?}",i+1,&doc_data);
                           i+=1;
                       }
                    }
                }
            }
        }
    }
}
$ cargo run
...
Document: 1. Document({"_id": ObjectId("63ee1b8b4b7c65e95ba891bd"), "originalId": ObjectId("6252fab17b201412088a4aaa"), "client": ObjectId("63d62de44370c4d5f1670f78"), "type": String("room"),...
...
Document: 36. Document({"_id": ObjectId("63ee1b8b4b7c65e95ba891e7"), "originalId": ObjectId("625300cb7b201412088a4d30"), "client": ObjectId("63d62de44370c4d5f1670f78"),...

Да...моя догадка оказалась верной. Файл .bson представляет собой серию Bson::Document(data), расположенных рядом с другим.

нередко использовать новую строку в качестве разделителя, но здесь даже нет разделителя, одно исключение среди многих в стеке Монго, поэтому это технический вопрос, проще анализировать документ за документом, а не создавать гигантский вектор документа во время анализа.

Stargateur 24.03.2024 15:54

@Stargateur ..да. Десериализатор BSON знает, где начинаются/кончаются его данные. Это удобно. Вы можете отправлять двоичные данные BSON по сети, не беспокоясь о флагах начала/конца данных.

ir1keren 24.03.2024 21:28

Другие вопросы по теме