Overview
En esta guía, puedes aprender cómo el driver de Go maneja las conversiones entre tipos BSON y tipos de Go. El proceso de convertir un tipo de Go a BSON se denomina marshallización, mientras que el proceso inverso se denomina unmarshallización.
Las siguientes secciones explican cómo el controlador Go representa los datos BSON y cómo puedes ajustar los comportamientos de serialización y deserialización por defecto.
Tipos de datos
MongoDB almacena documentos en una representación binaria llamada BSON que permite un procesamiento de datos sencillo y flexible.
El driver de Go proporciona cuatro tipos principales para trabajar con datos BSON:
D:: Una representación ordenada de un documento BSON (fracción)MUna representación no ordenada de un documento BSON (mapa)AUna representación ordenada de un arreglo BSONE: Un único elemento dentro de un tipo D
El siguiente ejemplo demuestra cómo construir un filtro de query utilizando el tipo bson.D para encontrar documentos en los que el valor del campo quantity sea mayor que 100:
filter := bson.D{{"quantity", bson.D{{"$gt", 100}}}}
Para obtener más información sobre cómo el driver de Go gestiona datos BSON, consulta la documentación API del paquete bson.
Etiquetas de estructura
En Go, una estructura es una colección de campos de datos con tipos de datos declarados. Puedes modificar el comportamiento predeterminado de serialización y deserialización de un campo de estructura utilizando etiquetas de estructura, que son piezas opcionales de metadatos adjuntas a los campos de la estructura. El uso más común de las etiquetas de estructura es especificar el nombre del campo en el documento BSON que corresponde al campo de la estructura. La siguiente tabla describe las etiquetas de estructura adicionales que puedes utilizar en el driver de Go:
Etiqueta de Struct | Descripción |
|---|---|
| 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 |
| Si el campo es de tipo |
| Si el tipo de campo es un tipo numérico que no sea de punto flotante, los BSON dobles no asignados a ese campo se truncarán en el punto decimal. |
| Si el tipo de campo es un campo struct o map, el campo se aplanará al realizar el marshalling y se des-aplanará al realizar el unmarshalling. |
Si no especificas etiquetas de estructura, el controlador de Go serializa las estructuras usando las siguientes reglas:
El controlador solo convierte a formato de intercambio y deshace la conversión de campos exportados.
El driver genera una clave BSON utilizando el campo de estructura correspondiente en minúsculas.
El driver ordena los campos de la estructura embebida como subdocumentos. Cada clave es la versión en minúsculas del tipo de campo.
El controlador agrupa un campo de puntero como el tipo subyacente si el puntero no es nulo. Si el puntero es nulo, el controlador lo serializa como un valor nulo de BSON.
Al desagrupar, el controlador Go sigue estas asignaciones de tipo D/M para los campos de
anytipo. El controlador desagrupa los documentos BSON desagrupados en unanycampo comoDtipo.
Opciones BSON
Se pueden especificar opciones BSON para ajustar el comportamiento de marshalling y unmarshalling de la instancia de Client. Para configurar opciones BSON en Client, crear y configurar una instancia de BSONOptions.
Este ejemplo realiza las siguientes acciones:
Crea una instancia
BSONOptionsconfigurando los siguientes ajustes:Establece el campo
UseJSONStructTagsentrue, lo que indica al controlador que utilice la etiqueta de estructura"json"si no se especifica una etiqueta de estructura"bson"Establece el campo
NilSliceAsEmptyentrue, lo que instruye al controlador a agruparnilslices de Go como arreglos de BSON vacíosEstablece el campo
OmitEmptyentrue, lo que indica al controlador que omita globalmente los valores vacíos del BSON serializado, en lugar de establecer los valores vacíos ennull
Pasa la instancia
BSONOptionsal método asistenteSetBSONOptions()para especificar una instanciaClientOptionsCrea un
Clientpara aplicar el comportamiento especificado de empaquetado y desempaquetado BSON
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.
Deserialización
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:
nilsi un documento coincidía con tu query y no hubo errores al recuperar y deserializar 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étodoDecode()y el métodoDecode()devuelve el error.
Cuando se usa 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 query.
El siguiente ejemplo demuestra cómo puedes utilizar el método Decode() para desmarcar y leer el resultado de una operación sencilla de 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}]
El tipo Cursor también utiliza el método All(), que deserializa todos los documentos almacenados en el cursor en un arreglo al mismo tiempo.
El paquete bson incluye una familia de Marshal() y Unmarshal() métodos que funcionan con datos codificados en BSON del tipo []byte. Los métodos bson.Marshal() y bson.Unmarshal() requieren un parámetro que pueda codificarse en un documento BSON, como un tipo bson.D. Se produce un error Write si pasas un tipo incorrecto. Por ejemplo, si pasas un string a bson.Marshal(), se produce un error WriteString.
El siguiente código muestra cómo puedes desensamblar BSON de nuevo en una estructura definida por el usuario usando 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 marshalling y unmarshalling utilizados con el tipo Cursor, consulta la documentación de la API Cursor.
Para obtener más información sobre los métodos de serialización y deserialización en el paquete bson, consulta la documentación de la API de bson.
Trabajar con datos BSON sin procesar
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:
Realización de búsquedas en campos específicos sin convertir el documento completo
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 familia de tipos Raw, consulte la documentación de la API Raw BSON.