Explore o novo chatbot do Developer Center! O MongoDB AI chatbot pode ser acessado na parte superior da sua navegação para responder a todas as suas perguntas sobre o MongoDB .

Junte-se a nós no Amazon Web Services re:Invent 2024! Saiba como usar o MongoDB para casos de uso de AI .
Desenvolvedor do MongoDB
Central de desenvolvedor do MongoDBchevron-right
Idiomaschevron-right
Rustchevron-right

Estruturando dados com Serde em Rust

Isabel Atkinson5 min read • Published Dec 16, 2021 • Updated Apr 23, 2024
MongoDBRust
Ícone do FacebookÍcone do Twitterícone do linkedin
Avalie esse Artigo
star-empty
star-empty
star-empty
star-empty
star-empty

Introdução

Este post detalha novas atualizações no Rust MongoDB Driver e biblioteca BSON para melhorar nossa integração com o Serde. Na publicação do blog Rust Quick Start, discute-se a complexidade de trabalhar com o BSON, que tem um esquema dinâmico, no Rust, que usa um sistema de tipos estáticos. O driver MongoDB Rust e a biblioteca BSON usam oSerde para facilitar a conversão entre estruturas e enums BSON e Rust. No 1.2.0 versões dessas duas bibliotecas, incluímos a nova integração do Serde para tornar o trabalho direto com seus próprios tipos de dados Rust mais fácil e fácil de usar.

Pré-requisitos

Esta publicação pressupõe que você tenha uma versão recente da cadeia de ferramentas Rust instalada (v1.44+) e que esteja familiarizado com a sintaxe Rust. Ele também pressupõe que você esteja familiarizado com a biblioteca Rust Serde.

Alterações no Driver

O 1.2.0 A versão do driver Rust introduz um parâmetro de tipo genérico para o tipocollection. O parâmetro genérico representa o tipo de dados que você deseja inserir e localizar de sua coleção MongoDB. Qualquer tipo de dados Rust que derive/implemente as características Serde Serialize e Deserialize pode ser usado como um parâmetro de tipo para uma collection.
Por exemplo, estou trabalhando com a seguinte estrutura que define o esquema dos dados em minha coleçãostudents:
1#[derive(Serialize, Deserialize)]
2struct Student {
3 name: String,
4 grade: u32,
5 test_scores: Vec<u32>,
6}
Posso criar um Collectiongenérico usando o métodoDatabase::collection_with_type e especificando Student como o tipo de dados com o qual estou trabalhando.
1let students: Collection<Student> = db.collection_with_type("students");
Antes da introdução do Collectiongenérico, os vários métodos CRUD Collection aceitavam e retornavam o tipo dedocumento. Isso significa que eu precisaria serializar minhas estruturasStudent para Documents antes de inseri-las na coleção dos alunos. Agora, posso inserir um Student diretamente na minha coleção:
1let student = Student {
2 name: "Emily".to_string(),
3 grade: 10,
4 test_scores: vec![98, 87, 100],
5};
6let result = students.insert_one(student, None).await;
Também posso encontrar um aluno diretamente em meu Collection:
1// student is of type Student
2let student = students.find_one(doc! { "name": "Emily" }, None).await?;
Talvez eu decida inserir um tipo diferente de dados na collectionstudents em algum momento. Embora minha coleçãostudents esteja restrita ao tipo de dadosStudent, posso criar facilmente um clone da coleçãostudents com um novo parâmetro de tipo:
1let students: Collection<CollegeStudent> = students.clone_with_type();
O tipo genérico padrão para Collection é Document. Isso significa que qualquer Collection criado sem um tipo genérico continuará a localizar e retornar o tipoDocument, e qualquer código existente que use Collection não será afetado por essas alterações.

Alterações do BSON

O 1.2. A versão 0 também inclui alterações na biblioteca Rust BSON que melhoram a usabilidade ao trabalhar com o Serde.

Funções auxiliares Serde

Às vezes, você pode querer serializar ou desserializar dados em suas estruturas ou enums de forma diferente do comportamento padrão. Serde fornece atributosserialize_with e deserialize_with que permitem especificar funções a serem usadas para serialização e desserialização em campos e variantes específicos.
A biblioteca BSON agora inclui um conjunto de funções que implementam estratégias comuns para serialização e desserialização personalizadas ao trabalhar com BSON. Você pode usar essas funções importando-as do módulo serde_helpersna caixabson-rust e usando os atributosserialize_with e deserialize_with . Algumas dessas funções são detalhadas abaixo.
Alguns usuários preferem representar o campo de ID do objeto em seus dados com uma string hexadecimal em vez do tipoObjectId da biblioteca BSON :
1#[derive(Serialize, Deserialize)]
2 struct Item {
3 oid: String,
4 // rest of fields
5}
Introduzimos um método para serializar uma string hexadecimal em um ObjectId no móduloserde_helpers chamado serialize_hex_string_as_object_id. Posso anotar meu campooid com esta função usando serialize_with:
1#[derive(Serialize, Deserialize)]
2struct Item {
3 #[serde(serialize_with = "serialize_hex_string_as_object_id")]
4 oid: String,
5 // rest of fields
6}
Agora, se eu serializar uma instância da estruturaItem em BSON, o campooid será representado por um ObjectId em vez de um string.
Também introduzimos módulos que lidam com a serialização e a desserialização. Por exemplo, talvez eu queira representar dados binários usando o tipoUuid na caixa uuid do Rust :
1#[derive(Serialize, Deserialize)]
2struct Item {
3 uuid: Uuid,
4 // rest of fields
5}
Como o BSON não tem um tipo de UUID específico, precisarei converter esses dados em binários se quiser serializar no BSON. Também gostaria de converter de volta para Uuid ao desserializar do BSON. O módulouuid_as_binary no módulo serde_helpers pode lidar com ambas as conversões. Adicionarei o seguinte atributo para usar este módulo:
1#[derive(Serialize, Deserialize)]
2struct Item {
3 #[serde(with = "uuid_as_binary")]
4 uuid: Uuid,
5 // rest of fields
6}
Agora posso trabalhar diretamente com o tipo Uuid sem precisar me preocupar em convertê-lo de e para BSON!
O móduloserde_helpers apresenta funções para diversas outras estratégias comuns; você pode conferir a documentação aqui.

Inteiros sem sinal

A especificação BSON define dois tipos de inteiros: um inteiro de 32 bits com sinal e um inteiro de 64 bits com sinal. Isso pode evitar desafios quando você tenta inserir dados com números inteiros sem sinal em suas coleções.
Minha Student estrutura do exemplo anterior contém números inteiros sem sinal grade nos test_score campos e . As versões anteriores da biblioteca BSON retornariam um erro se eu tentasse serializar uma instância dessa estrutura em Document, pois nem sempre há um mapeamento claro entre os tipos inteiros não assinados e assinados. No entanto, muitos números inteiros não assinados podem caber em tipos assinados! Por exemplo, talvez eu queira criar o seguinte aluno:
1let student = Student {
2 name: "Alyson".to_string(),
3 grade: 11,
4 test_scores: vec![89, 92, 99],
5};
Embora os números nos camposgrade e test_scores sejam técnicamente inteiros 32 bits sem sinal, eles podem ser convertidos em inteiros 32 bits com assinatura sem perder nenhum dado.
O 1.2. A versão 0 da biblioteca BSON não retorna mais um erro ao tentar serializar números inteiros não assinados em BSON e, em vez disso, tenta realizar uma conversão sem perdas em um dos BSON types assinados. Se o inteiro sem sinal não puder ser convertido em um inteiro de 32 ou 64 bit assinado, a serialização ainda retornará um erro.
Agora, posso converter meu struct de aluno em um Document:
1let doc = to_document(&student)?;
Posso usar println! para ver que o seguinte Document é retornado:
1Document({
2 "name": String("Alyson"),
3 "grade": Int32(11),
4 "test_scores": Array([Int32(89), Int32(92), Int32(99)])
5})

Conclusão

O Serde é uma ferramenta poderosa que oferece muitas funcionalidades para personalizar a maneira como você converte entre diferentes formatos de dados. No 1, .2.0 versões do driver Rust e da biblioteca BSON, ficou ainda mais fácil trabalhar diretamente com seus tipos de dados do Rust. Se você estiver interessado em recursos de mapeamento mais complexos, vale a pena ler a documentação do Serde sobre atributos. Para obter mais detalhes sobre como trabalhar com o MongoDB no Rust, você pode conferir a documentação do driver Rust e dabiblioteca BSON. Também aceitamos contribuições na forma de solicitações de pull do Github - consulte a seção em nosso README para obter informações sobre como executar nossos testes.
Se tiver dúvidas, acesse o site da nossa comunidade de desenvolvedores, no qual os engenheiros e a comunidade do MongoDB ajudarão você a desenvolver sua próxima grande ideia com o MongoDB.

Ícone do FacebookÍcone do Twitterícone do linkedin
Avalie esse Artigo
star-empty
star-empty
star-empty
star-empty
star-empty
Relacionado
Artigo

Como o Prisma analisa um esquema de um banco de dados MongoDB


May 19, 2022 | 8 min read
Início rápido

Introdução a pipelines de agregação em Rust


Oct 01, 2024 | 15 min read
Tutorial

Red Mosquitto: Implemente um sensor de ruído com um cliente MQTT em um ESP32


Sep 17, 2024 | 25 min read
Tutorial

Escrevendo uma API com MongoDB no Rust


Jun 10, 2024 | 10 min read
Sumário
  • Introdução