MongoDB
MongoDB es una base de datos de documentos. Su unidad básica de datos son documentos almacenados en formato BSON (Binary JSON), una estructura similar a JSON. La estructura flexible permite almacenar diferentes tipos de datos, siendo más flexible que las bases de datos relacionales. Además, usa JavaScript como lenguaje de scripting para realizar operaciones combinadas mediante scripts. Este artículo presenta principalmente el uso del controlador oficial de mongo en Go para operar la base de datos MongoDB. No es un tutorial de MongoDB; si no tienes experiencia con Mongo, por favor infórmate y aprende primero por tu cuenta.
Documentación de MongoDB: Introduction to MongoDB — MongoDB Manual
Controlador
Hay pocas bibliotecas para MongoDB en Go. Algunas bibliotecas mantenidas por la comunidad dejaron de mantenerse, pero el controlador oficial de mongo es completamente suficiente.
Repositorio: mongodb/mongo-go-driver: The Official Golang driver for MongoDB (github.com)
Documentación: mongodb/mongo-go-driver: The Official Golang driver for MongoDB (github.com)
Instalación
Para descargar la dependencia, usa la siguiente dirección:
$ go get go.mongodb.org/mongo-driver/mongoConexión
A continuación se muestra un ejemplo simple de cómo un cliente mongo establece una conexión con el servidor:
package main
import (
"context"
"fmt"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"go.mongodb.org/mongo-driver/mongo/readpref"
"log"
)
func main() {
ctx := context.Background()
// Establecer conexión usando URI
client, err := mongo.Connect(ctx, options.Client().ApplyURI("mongodb://admin:123456@192.168.48.138:27017/"))
if err != nil {
log.Panicln(err)
}
// Cerrar conexión
defer client.Disconnect(ctx)
// Prueba ping para verificar si la conexión está disponible
fmt.Println(client.Ping(ctx, readpref.Primary()))
}bson
MongoDB usa los siguientes tipos en Go para mapear documentos en la base de datos, ubicados en bson/bson.go:
// Representación ordenada de un documento BSON
type D = primitive.D
// Un par clave-valor, unidad básica de representación ordenada de documentos BSON
type E = primitive.E
// Representación desordenada de un documento BSON
type M = primitive.M
// Representación ordenada de datos BSON
type A = primitive.ASus tipos reales son los siguientes:
// Representación ordenada de un documento BSON
type D []E
// Un par clave-valor, unidad básica de representación ordenada de documentos BSON
type E struct {
Key string
Value interface{}
}
// Representación desordenada de un documento BSON
type M map[string]interface{}
// Representación ordenada de datos BSON
type A []interface{}Con estos tipos, puedes construir consultas SQL o mapear datos.
TIP
El directorio examples del controlador tiene bastantes ejemplos de uso. La documentación oficial demuestra en detalle cómo usar los cuatro tipos mencionados.
Consultar documentos
Ejemplo oficial de consulta: mongo-go-driver/examples/documentation_examples/examples.go at master · mongodb/mongo-go-driver (github.com)
Primero crea la base de datos user e inserta los siguientes datos en la colección users:
> use user
> db.users.insertMany([
{
name: "mike",
age: 12,
},
{
name: "jenny",
age: 14,
},
{
name: "jack",
age: 18,
address: "usa"
}
])Consultar uno
type User struct {
Name string `bson:"name"`
Age int `bson:"age"`
Address string `bson:"address"`
}
var user User
result := client.Database("user"). // Seleccionar base de datos
Collection("users"). // Seleccionar colección
FindOne(ctx, bson.D{{"address", "usa"}}) // Condición de filtro
// Deserializar
if err := result.Decode(&user); err != nil {
log.Panicln(err)
}
fmt.Printf("%+v\n", user)El código de consulta anterior es equivalente a:
db.users.findOne({
address: "usa"
})Resultado:
{Name:jack Age:18 Address:usa}Consultar varios
type User struct {
Name string `bson:"name"`
Age int `bson:"age"`
Address string `bson:"address"`
}
var users []User
cursor, err := client.Database("user"). // Seleccionar base de datos
Collection("users"). // Seleccionar colección
Find(ctx, bson.D{}) // Condición de filtro
if err != nil {
log.Panicln(err)
}
if err := cursor.All(ctx, &users); err != nil {
log.Panicln(err)
}
fmt.Printf("%+v\n", users)Equivalente a:
db.users.find({})Salida:
[{Name:jack Age:18 Address:usa} {Name:mike Age:12 Address:} {Name:jenny Age:14 Address:}]Al construir condiciones de consulta, también puedes usar options:
type User struct {
Name string `bson:"name"`
Age int `bson:"age"`
Address string `bson:"address"`
}
var users []User
find := options.Find()
find.SetSort(bson.M{"age": 1})
find.SetLimit(1)
cursor, err := client.Database("user"). // Seleccionar base de datos
Collection("users"). // Seleccionar colección
Find(ctx, bson.D{}, find) // Condición de filtro
if err != nil {
log.Panicln(err)
}
if err := cursor.All(ctx, &users); err != nil {
log.Panicln(err)
}
fmt.Printf("%+v\n", users)Equivalente a:
db.users.find({}).sort({age:1}).limit(1)Salida:
[{Name:mike Age:12 Address:}]Crear documentos
Ejemplo oficial de creación: mongo-go-driver/examples/documentation_examples/examples.go at master · mongodb/mongo-go-driver (github.com)
A continuación se muestra un ejemplo de creación de un documento:
one, err := client.Database("user").Collection("users").InsertOne(ctx, User{
Name: "lili",
Age: 20,
Address: "china",
})
if err != nil {
log.Panicln(err)
}
fmt.Println(one.InsertedID)Después de crear exitosamente, devuelve el ObjectID del documento:
ObjectID("64c60fa01e2548d9e4de6cf4")A continuación se muestra un ejemplo de creación de múltiples documentos:
users := []any{User{
Name: "john",
Age: 10,
Address: "usa",
}, User{
Name: "pop",
Age: 30,
Address: "uk",
}}
one, err := client.Database("user").Collection("users").InsertMany(ctx, users)
if err != nil {
log.Panicln(err)
}
fmt.Println(one.InsertedIDs)Después de crear exitosamente, devuelve un conjunto de ObjectID:
[ObjectID("64c610d5aec2618d6ca0b515") ObjectID("64c610d5aec2618d6ca0b516")]Los dos códigos anteriores son equivalentes a db.users.insertOne y db.users.insertMany.
Actualizar documentos
Ejemplo oficial de actualización: mongo-go-driver/examples/documentation_examples/examples.go at master · mongodb/mongo-go-driver (github.com)
A continuación se muestra un ejemplo de actualización de un solo documento, cambiando el nombre de lili a mark:
upres, err := client.Database("user").Collection("users").UpdateOne(ctx, bson.D{
{"name", "mark"},
},
bson.D{
{"$set", bson.D{
{"name", "lili"},
}},
})
if err != nil {
log.Panicln(err)
}
fmt.Printf("%+v", upres)Equivalente a:
db.users.updateOne({
name: "lili"
}, {
$set: {
name: "mark"
},
})Salida:
&{MatchedCount:1 ModifiedCount:1 UpsertedCount:0 UpsertedID:<nil>}A continuación se muestra un ejemplo de actualización de múltiples documentos, actualizando la dirección de las personas con edad 10 a cn:
upres, err := client.Database("user").Collection("users").UpdateMany(ctx, bson.D{
{"age", 10},
},
bson.D{
{"$set", bson.D{
{"address", "cn"},
}},
})
if err != nil {
log.Panicln(err)
}
fmt.Printf("%+v", upres)Además de usar Update, Mongo también proporciona Replace. La diferencia entre los dos es que el primero actualiza campos del documento, mientras que el segundo reemplaza completamente el documento. Por ejemplo, en el siguiente código ya no se necesitan operadores:
upres, err := client.Database("user").Collection("users").ReplaceOne(ctx, bson.D{
{"age", 10},
},
bson.D{
{"address", "cn"},
})
if err != nil {
log.Panicln(err)
}
fmt.Printf("%+v", upres)Al mismo tiempo, Mongo también proporciona FindOneAndUpdate y FindOneAndReplace para obtener y actualizar documentos. Como sigue:
res := client.Database("user").Collection("users").FindOneAndReplace(ctx, bson.D{
{"address", "cn"},
},
bson.D{
{"address", "uk"},
})
if err := res.Err(); err != nil {
log.Panicln(err)
}
var user User
res.Decode(&user)
fmt.Printf("%+v", user)Salida:
Name: Age:0 Address:cn}Esta operación consulta primero el documento y luego lo modifica.
Eliminar documentos
Ejemplo oficial de eliminación: mongo-go-driver/examples/documentation_examples/examples.go at master · mongodb/mongo-go-driver (github.com)
A continuación se muestra un ejemplo de eliminación de un documento:
result, err := client.Database("user").Collection("users").DeleteOne(ctx, bson.D{
{"name", "jack"},
})
if err != nil {
log.Panicln(err)
}
fmt.Println(result.DeletedCount)A continuación se muestra un ejemplo de eliminación de múltiples documentos:
result, err := client.Database("user").Collection("users").DeleteMany(ctx, bson.D{
{"age", "10"},
})
if err != nil {
log.Panicln(err)
}
fmt.Println(result.DeletedCount)Agregación
Ejemplo oficial de agregación: mongo-go-driver/examples/documentation_examples/examples.go at master · mongodb/mongo-go-driver (github.com)
La operación de agregación usa el tipo mongo.Pipeline, que es esencialmente []bson.D:
type Pipeline []bson.Dpipline := mongo.Pipeline{
{
{"$match", bson.D{
{"address", "uk"},
}},
},
{
{"$sort", bson.D{
{"age", 1},
}},
},
}
aggregate, err := client.Database("user").Collection("users").Aggregate(ctx, pipline)
if err != nil {
log.Panicln(err)
}
var users []User
if err := aggregate.All(ctx, &users); err != nil {
log.Panicln(err)
}
log.Println(users)Salida:
[{lili 20 uk} {kak 30 uk}]Esta operación de agregación coincide con todos los usuarios cuya dirección es uk y luego los ordena por edad.
