Join us Sept 17 at .local NYC! Use code WEB50 to save 50% on tickets. Learn more >
MongoDB Event
Menu Docs
Página inicial do Docs
/ / /
Driver GO
/

Trabalhe com BSON

Neste guia, você aprenderá como o driver Go lida com conversões entre os tipos BSON e Go. O processo de conversão de um tipo Go para BSON é chamado de ordenação, enquanto o processo inverso é chamado de desordenação.

As seções a seguir explicam como o driver Go representa os dados BSON e como você pode ajustar os comportamentos padrão de ordenação e desordenação.

O MongoDB armazena documentos em uma representação binária denominada BSON que permite o processamento de dados fácil e flexível.

O driver Go oferece quatro tipos principais de trabalho com dados BSON:

  • D: Uma representação ordenada de um documento BSON (fatia)

  • M: Uma representação não ordenada de um documento BSON (mapa)

  • A: Uma representação ordenada de uma array BSON

  • E: Um único elemento dentro de um tipo D

O exemplo abaixo mostra como criar um filtro de queries utilizando o tipo bson.D para corresponder documentos em que o valor do campo quantity é maior que 100:

filter := bson.D{{"quantity", bson.D{{"$gt", 100}}}}

Para saber mais sobre como o driver Go lida com os dados BSON, consulte a documentação da API do pacote bson.

No Go, uma estrutura é uma collection de campos de dados com tipos de dados declarados. Você pode modificar o comportamento padrão de transferência e remoção de transferência de um campo de estrutura usando marcações de estrutura, que são partes opcionais de metadados anexadas aos campos de estrutura. O uso mais comum de marcações de estrutura é especificar o nome do campo no documento BSON que corresponde ao campo estruturado. A tabela a seguir descreve as marcações de estrutura adicionais que você pode usar no driver Go:

Marcação de estrutura
Descrição

omitempty

O campo não será ordenado se estiver definido para o valor zero correspondente ao tipo de campo.

minsize

Se o campo for do tipo int64, uint, uint32 ou uint64 e o valor do campo puder caber em um int32 assinado, o campo será serializado como um BSON int32 em vez de um BSON int64. Se o valor não couber em um int32 registrado, essa marcação será ignorada.

truncate

Se o tipo de campo for um tipo numérico não flutuante, o que BSON dobrar sem ordenação nesse campo será truncado no ponto decimal.

inline

Se o tipo de campo for um campo de estrutura ou mapa, o campo será achatado ao ser ordenado e não será achatado ao ser desordenado.

Se você não especificar marcações de estrutura, o driver Go organizará as estruturas usando as seguintes regras:

  1. O driver apenas ordena e desordena os campos exportados.

  2. O driver gera uma chave BSON utilizando a letra minúscula do campo de estrutura correspondente.

  3. O driver ordena campos de estrutura integrados como subdocumentos. Cada chave é a letra minúscula do tipo de campo.

  4. O driver ordena um campo de ponteiro como o tipo subjacente se o ponteiro for diferente de nulo. Se o ponteiro for nulo, o driver o ordenará como um valor nulo BSON.

  5. Ao desordenar, o driver Go segue esses mapeamentos tipo D/M para campos do tipo interface{}. O driver desordena documentos BSON desordenados em um campo interface{} como um tipo D.

O exemplo a seguir demonstra como o driver Go transforma uma estrutura em uma struct com várias tags de estrutura:

type Address struct {
Street string
City string
State string
}
type Student struct {
FirstName string `bson:"first_name,omitempty"`
LastName string `bson:"last_name,omitempty"`
Address Address `bson:"inline"`
Age int
}
coll := client.Database("db").Collection("students")
address1 := Address{ "1 Lakewood Way", "Elwood City", "PA" }
student1 := Student{ FirstName : "Arthur", Address : address1, Age : 8}
_, err = coll.InsertOne(context.TODO(), student1)

A representação BSON correspondente tem a seguinte aparência:

{
"_id" : ObjectId("..."),
"first_name" : "Arthur",
"street" : "1 Lakewood Way",
"city" : "Elwood City",
"state" : "PA",
"age" : 8
}

Neste exemplo, as tags estruturadas fazem o driver:

  • Defina nomes de campos BSON personalizados, como first_name

  • Omitir o campo LastName vazio

  • Nivelar a estrutura aninhada e levar todos os campos até o nível superior

O exemplo a seguir demonstra como o driver Go transforma uma estrutura sem nenhuma tag de estrutura:

type Address struct {
Street string
City string
State string
}
type Student struct {
FirstName string
LastName string
Address Address
Age int
}
coll := client.Database("db").Collection("students")
address1 := Address{ "1 Lakewood Way", "Elwood City", "PA" }
student1 := Student{ FirstName : "Arthur", Address : address1, Age : 8}
_, err = coll.InsertOne(context.TODO(), student1)

A representação BSON correspondente tem a seguinte aparência:

{
"_id" : ObjectId("..."),
"firstname" : "Arthur",
"lastname" : "",
"address": {
"street" : "1 Lakewood Way",
"city" : "Elwood City",
"state" : "PA"
},
"age" : 8
}

Sem marcações estruturadas, o driver:

  • Define as letras minúsculas dos campos estruturados como os nomes do campo BSON

  • Inclui um campo lastname vazio

  • Armazena o campo Address como um valor aninhado

Você pode especificar opções BSON para ajustar o comportamento de ordenação e desordenação de sua instância Client. Para definir opções de BSON no seu Client, crie e configure uma instância do BSONOptions.

Este exemplo executa as seguintes ações:

  • Cria uma instância BSONOptions definindo as seguintes configurações:

    • Define o campo UseJSONStructTags como true, que instrui o driver a usar a marcação "json" de estrutura se uma marcação "bson" de estrutura não for especificada

    • Define o campo NilSliceAsEmpty como true, que instrui o driver a ordenar fatias nil Go como arrays BSON vazias

  • Passa a instância BSONOptions para o método auxiliar SetBSONOptions() para especificar uma instância ClientOptions

  • Cria um Client para aplicar o comportamento de ordenação e desordenação de BSON especificado

bsonOpts := &options.BSONOptions {
UseJSONStructTags: true,
NilSliceAsEmpty: true,
}
clientOpts := options.Client().
ApplyURI("<connection string>").
SetBSONOptions(bsonOpts)
client, err := mongo.Connect(clientOpts)

Dica

Para saber mais sobre o tipo BSONOptions, consulte a documentação da API de BSONOptions. Para um exemplo que especifica uma instância BSONOptions e cria um cliente com estas opções, consulte o exemplo Connect() BSONOptions.

Você pode desordenar documentos BSON utilizando o método Decode() no resultado do método FindOne ou qualquer instância *mongo.Cursor.

O método Decode() retorna um tipo de error que contém um dos seguintes valores:

  • nil se um documento corresponder à sua query e não houver erros ao recuperar e desordenar o documento.

  • Se o driver recuperou o documento, mas não pôde desordenar o resultado, o método Decode() retorna o erro de desordenação.

  • Se houver um erro ao recuperar seu documento durante a execução do método FindOne(), o erro se propagará para o método Decode() e o método Decode() retornará o erro.

Quando utilizado no tipo SingleResult retornado pelo método FindOne(), o Decode() também pode retornar o erro ErrNoDocuments se nenhum documento corresponder ao filtro de query.

O exemplo seguinte demonstra como você pode utilizar o método Decode() para desordenar e ler o resultado de uma operação simples do FindOne():

coll := client.Database("db").Collection("students")
filter := bson.D{{"age", 8}}
var result bson.D
err := coll.FindOne(context.TODO(), filter).Decode(&result)
fmt.Println(result)
[{_id ObjectID("...")} {first_name Arthur} {street 1 Fern Way} {city Elwood City} {state PA} {age 8}]

O tipo Cursor também utiliza o método All(), que une todos os documentos armazenados no cursor em uma array ao mesmo tempo.

O pacote bson inclui uma família de métodos Marshal() e Unmarshal() que funcionam com dados codificados por BSONs do tipo []byte. Os métodos bson.Marshal() e bson.Unmarshal() exigem um parâmetro que pode ser codificado em um documento BSON, como um tipo bson.D. Um erro Write ocorrerá se você passar um tipo incorreto. Por exemplo, se você passar uma string para bson.Marshal(), ocorrerá um erro WriteString.

O código a seguir demonstra como você pode desordenar o BSON de volta para uma estrutura definida pelo usuário usando métodos do pacote bson:

type Item struct {
Category string
Quantity int32
}
doc, err := bson.Marshal(bson.D{{"category", "plate"}, {"quantity", 6}})
var test Item
err = bson.Unmarshal(doc, &test)
fmt.Printf("Unmarshalled Struct:\n%+v\n", test)
Unmarshalled Struct:
{Category:plate Quantity:6}

Observação

Você pode usar o tipo Raw para recuperar elementos de uma fatia de bytes de documento BSON sem desordená-lo para um tipo Go. Esse tipo permite procurar elementos individuais sem desordenar todo o documento BSON . Para obter mais informações sobre como usar o tipo Raw, consulte a seção Trabalhar com dados brutos BSON.

Para saber mais sobre os métodos de ordenação e desordenação usados com o tipo Cursor, consulte a documentação da API do cursor.

Para saber mais sobre os métodos de ordenação e desordenação no pacote bson, consulte a documentação da API BSON.

O driver Go suporta trabalhar com documentos BSON brutos por meio do tipo Raw. O tipo Raw permite validar e recuperar elementos de uma fatia de bytes sem desordenar todo o documento BSON. Isso é útil nas seguintes situações:

  • Realizando pesquisas em campos específicos sem converter todo o documento

  • Reduzindo a sobrecarga de memória evitando a desordenação completa de documento

  • Trabalhando diretamente com dados BSON binários recebidos do banco de dados

O tipo Raw fornece métodos para validar o documento BSON e procurar elementos individuais por suas chaves. O exemplo a seguir demonstra como validar um documento BSON bruto e recuperar um campo específico dele:

collection := client.Database("sample_restaurants").Collection("restaurants")
findOptions := options.FindOne()
var raw bson.Raw
err = collection.FindOne(
context.TODO(),
bson.D{{"name", "Mongo's Pizza"}},
findOptions,
).Decode(&raw)
if err != nil {
log.Fatalf("Failed to find document: %v", err)
}
// Print the document type
fmt.Printf("Document type: %T\n", raw)
// Access a field from the raw document
name := raw.Lookup("name").StringValue()
fmt.Println("Restaurant name:", name)
Document type: bson.Raw
Restaurant name: Mongo's Pizza

Para saber mais sobre a família de tipos Raw, consulte a documentação da API de BSON bruto.

Voltar

Usar tags estruturadas

Nesta página