Skip to content

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:

sh
$ go get go.mongodb.org/mongo-driver/mongo

Conexión

A continuación se muestra un ejemplo simple de cómo un cliente mongo establece una conexión con el servidor:

go
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:

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.A

Sus tipos reales son los siguientes:

go
// 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.

Dirección: mongo-go-driver/examples/documentation_examples/examples.go at master · mongodb/mongo-go-driver (github.com)

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:

sql
> use user
> db.users.insertMany([
    {
        name: "mike",
        age: 12,

    },
    {
        name: "jenny",
        age: 14,

    },
    {
        name: "jack",
        age: 18,
        address: "usa"
    }
])

Consultar uno

go
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:

sql
db.users.findOne({
    address: "usa"
})

Resultado:

{Name:jack Age:18 Address:usa}

Consultar varios

go
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:

sql
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:

go
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:

go
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:

go
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:

go
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:

sql
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:

go
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:

go
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:

go
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:

go
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:

go
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:

go
type Pipeline []bson.D
go
pipline := 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.

Golang editado por www.golangdev.cn