Docs Menu
Docs Home
/ /

Trabajar con BSON

En esta guía, aprenderá cómo el controlador Go gestiona las conversiones entre tipos BSON y Go. El proceso de convertir un tipo Go a BSON se denomina serialización, mientras que el proceso inverso se denomina desmarshalling.

Las siguientes secciones explican cómo el controlador Go representa los datos BSON y cómo se pueden ajustar los comportamientos de serialización y desserialización predeterminados.

MongoDB almacena documentos en una representación binaria llamada BSON que permite un procesamiento de datos fácil y flexible.

El driver de Go proporciona cuatro tipos principales para trabajar con datos BSON:

  • D:Una representación ordenada de un documento BSON (sección)

  • M:Una representación desordenada de un documento BSON (mapa)

  • A:Una representación ordenada de una matriz BSON

  • E: Un único elemento dentro de un tipo D

El siguiente ejemplo demuestra cómo construir un filtro de consulta utilizando el tipo bson.D para hacer coincidir documentos en los que el valor del campo quantity es mayor que 100:

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

Para obtener más información sobre cómo el controlador Go maneja los datos BSON, consulte la documentación de la API del paquete bson.

En Go, una estructura es una colección de campos de datos con tipos de datos declarados. Se puede modificar el comportamiento predeterminado de serialización y desmarshaling de un campo de estructura mediante etiquetas de estructura, que son metadatos opcionales adjuntos a los campos de estructura. El uso más común de las etiquetas de estructura es especificar el nombre del campo en el documento BSON correspondiente al campo de estructura. La siguiente tabla describe las etiquetas de estructura adicionales que se pueden usar en el controlador de Go:

Etiqueta de estructura
Descripción

omitempty

El campo no se serializará si se establece en el valor cero correspondiente al tipo de campo. Para evitar globalmente que el controlador serialice campos con valor cero, puede configurar la opción BSON OmitEmpty. Para obtener más información sobre cómo configurar la opción BSON OmitEmpty, consulte el ejemplo en Sección Opciones BSON de esta página.

minsize

Si el campo es de tipo int64, uint, uint32 o uint64 y su valor cabe en un int32 con signo, se serializará como un BSON int32 en lugar de un BSON int64. Si el valor no cabe en un int32 con signo, esta etiqueta se ignora.

truncate

Si el tipo de campo es un tipo numérico no flotante, los BSON dobles no serializados en ese campo se truncarán en el punto decimal.

inline

Si el tipo de campo es un campo de estructura o de mapa, el campo se aplanará al serializar y se desaplanará al desserializar.

Si no especifica etiquetas de estructura, el controlador Go ordena las estructuras utilizando las siguientes reglas:

  1. El controlador solo convierte a formato de intercambio y deshace la conversión de campos exportados.

  2. El controlador genera una clave BSON utilizando las minúsculas del campo de estructura correspondiente.

  3. El controlador ordena los campos de estructura incrustados como subdocumentos. Cada clave corresponde a la minúscula del tipo del campo.

  4. El controlador serializa un campo de puntero como tipo subyacente si el puntero no es nulo. Si el puntero es nulo, el controlador lo serializa como un valor nulo BSON.

  5. Al desagrupar, el controlador Go sigue estas asignaciones de tipo D/M para los campos de any tipo. El controlador desagrupa los documentos BSON desagrupados en un any campo como D tipo.

El siguiente ejemplo demuestra cómo el controlador Go ordena una estructura con varias etiquetas de estructura:

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)

La representación BSON correspondiente se ve así:

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

En este ejemplo, las etiquetas de estructura crean el controlador:

  • Define nombres de campo BSON personalizados como first_name

  • Omitir el campo vacío LastName

  • Aplanar la estructura anidada y llevar todos los campos al nivel superior

El siguiente ejemplo demuestra cómo el controlador Go ordena una estructura sin ninguna etiqueta de estructura:

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)

La representación BSON correspondiente se ve así:

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

Sin etiquetas de estructura, el controlador:

  • Establece las minúsculas de los campos de estructura como los nombres de campo BSON

  • Incluye un campo lastname vacío

  • Almacena el campo Address como un valor anidado

Puede especificar opciones de BSON para ajustar el comportamiento de serialización y desmarshalling de su instancia Client. Para configurar las opciones de BSON en su instancia Client, cree y configure una instancia BSONOptions.

Este ejemplo realiza las siguientes acciones:

  • Crea una instancia BSONOptions configurando los siguientes ajustes:

    • Establece el campo UseJSONStructTags en true, lo que indica al controlador que utilice la etiqueta de estructura "json" si no se especifica una etiqueta de estructura "bson"

    • Establece el campo NilSliceAsEmpty en true, lo que indica al controlador que ordene nil porciones de Go como matrices BSON vacías

    • Establece el campo OmitEmpty en true, lo que indica al controlador que omita globalmente los valores vacíos del BSON serializado, en lugar de establecer los valores vacíos en null

  • Pasa la instancia BSONOptions al método auxiliar SetBSONOptions() para especificar una instancia ClientOptions

  • Crea un Client para aplicar el comportamiento de serialización y desmarshalling de BSON especificado

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

Tip

Para obtener más información sobre el BSONOptions tipo, consulte la documentación de la API BSONOptions. Para ver un ejemplo que especifica una BSONOptions instancia y crea un cliente con estas opciones, consulte el ejemplo Connect() de BSONOptions.

Puede desorganizar documentos BSON utilizando el método Decode() en el resultado del método FindOne o cualquier instancia *mongo.Cursor.

El método Decode() devuelve un tipo error que contiene uno de los siguientes valores:

  • nil si un documento coincidió con su consulta y no hubo errores al recuperar y desorganizar el documento.

  • Si el controlador recuperó su documento pero no pudo descomponer el resultado, el método Decode() devuelve el error de descomposición.

  • Si hubo un error al recuperar su documento durante la ejecución del método FindOne(), el error se propaga al método Decode() y el método Decode() devuelve el error.

Cuando se utiliza en el tipo SingleResult devuelto por el método FindOne(), Decode() también puede devolver el error ErrNoDocuments si ningún documento coincide con el filtro de consulta.

El siguiente ejemplo demuestra cómo se puede utilizar el método Decode() para descomponer y leer el resultado de una operación FindOne() simple:

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}]

El tipo Cursor también utiliza el método All(), que desagrupa todos los documentos almacenados en el cursor en una matriz al mismo tiempo.

El paquete bson incluye una familia de métodos Marshal() y Unmarshal() que funcionan con datos codificados en BSON de tipo []byte. Los métodos bson.Marshal() y bson.Unmarshal() requieren un parámetro que pueda codificarse en un documento BSON, como el tipo bson.D. Se produce un error Write si se pasa un tipo incorrecto. Por ejemplo, si se pasa una cadena a bson.Marshal(), se produce un error WriteString.

El siguiente código demuestra cómo se puede deshacer la serialización de BSON y volver a convertirla en una estructura definida por el usuario mediante métodos del paquete 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}

Nota

Puede usar el Raw tipo para recuperar elementos de un fragmento de bytes de un documento BSON sin desmarshalarlo a un tipo Go. Este tipo permite buscar elementos individuales sin desmarshalar todo el documento BSON. Para obtener más información sobre cómo usar el Raw tipo, consulte la sección "Trabajar con datos BSON sin procesar".

Para obtener más información sobre los métodos de serialización y desmarshalling utilizados con el Cursor tipo, consulte la documentación de la API de Cursor.

Para obtener más información sobre los métodos de serialización y desmarshalling en el bson paquete, consulte la documentación de la API de bson.

El controlador Go admite el trabajo con documentos BSON sin procesar mediante el tipo Raw. El tipo Raw permite validar y recuperar elementos de un fragmento de bytes sin desmarshalar todo el documento BSON. Esto resulta útil en las siguientes situaciones:

  • Realizar búsquedas en campos específicos sin convertir todo el documento

  • Reducir la sobrecarga de memoria al evitar la desorganización completa del documento

  • Trabajar directamente con datos binarios BSON recibidos de la base de datos

El tipo Raw proporciona métodos para validar el documento BSON y buscar elementos individuales por sus claves. El siguiente ejemplo muestra cómo validar un documento BSON sin procesar y recuperar un campo específico:

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 obtener más información sobre la Raw familia de tipos, consulte la documentación de la API Raw BSON.

Volver

Usar etiquetas de struct

En esta página