MongoDB
MongoDB è un database di documenti, la sua unità dati di base è il documento, archiviato in formato BSON (Binary JSON), una struttura simile a JSON. La struttura flessibile consente di archiviare diversi tipi di dati, rendendolo più flessibile rispetto ai database relazionali, e utilizza JavaScript come linguaggio di scripting per completare operazioni combinate tramite script. Questo articolo introduce principalmente l'uso del driver ufficiale mongo in Go per operare il database MongoDB, non è un tutorial su MongoDB. Se non hai familiarità con MongoDB, ti preghiamo di informarti e studiare prima autonomamente.
Documentazione MongoDB: Introduction to MongoDB — MongoDB Manual
Driver
Le librerie per Go relative a MongoDB sono relativamente poche. Inizialmente c'erano alcune librerie mantenute dalla comunità, che successivamente hanno smesso di essere mantenute. Tuttavia, il driver ufficiale mongo è già più che sufficiente per l'uso.
Repository open source: mongodb/mongo-go-driver: The Official Golang driver for MongoDB (github.com)
Indirizzo documentazione: mongodb/mongo-go-driver: The Official Golang driver for MongoDB (github.com)
Installazione
Per scaricare le dipendenze, utilizzare il seguente indirizzo.
$ go get go.mongodb.org/mongo-driver/mongoConnessione
Di seguito è riportato un semplice esempio di connessione tra un client mongo e il server.
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()
// Stabilire connessione utilizzando l'URI
client, err := mongo.Connect(ctx, options.Client().ApplyURI("mongodb://admin:123456@192.168.48.138:27017/"))
if err != nil {
log.Panicln(err)
}
// Chiudere connessione
defer client.Disconnect(ctx)
// Test ping per verificare se la connessione è disponibile
fmt.Println(client.Ping(ctx, readpref.Primary()))
}bson
MongoDB utilizza i seguenti tipi in Go per mappare i documenti nel database, situati in bson/bson.go
// Rappresentazione ordinata di un documento BSON
type D = primitive.D
// Una coppia chiave-valore, unità base della rappresentazione ordinata di un documento BSON
type E = primitive.E
// Rappresentazione non ordinata di un documento BSON
type M = primitive.M
// Rappresentazione ordinata di dati BSON
type A = primitive.AI loro tipi effettivi sono i seguenti
// Rappresentazione ordinata di un documento BSON
type D []E
// Una coppia chiave-valore, unità base della rappresentazione ordinata di un documento BSON
type E struct {
Key string
Value interface{}
}
// Rappresentazione non ordinata di un documento BSON
type M map[string]interface{}
// Rappresentazione ordinata di dati BSON
type A []interface{}Utilizzando questi tipi, è possibile sia costruire query SQL che mappare dati.
TIP
La directory examples del driver contiene numerosi esempi di utilizzo. L'ufficialità dimostra in modo molto dettagliato come utilizzare i quattro tipi sopra menzionati.
Interrogare documenti
Esempio ufficiale di interrogazione: mongo-go-driver/examples/documentation_examples/examples.go at master · mongodb/mongo-go-driver (github.com)
Prima creare il database user, inserire i seguenti dati nella collection users
> use user
> db.users.insertMany([
{
name: "mike",
age: 12,
},
{
name: "jenny",
age: 14,
},
{
name: "jack",
age: 18,
address: "usa"
}
])Interrogazione singola
type User struct {
Name string `bson:"name"`
Age int `bson:"age"`
Address string `bson:"address"`
}
var user User
result := client.Database("user"). // Seleziona database
Collection("users"). // Seleziona collection
FindOne(ctx, bson.D{{"address", "usa"}}) // Condizione di filtro
// Deserializzazione
if err := result.Decode(&user); err != nil {
log.Panicln(err)
}
fmt.Printf("%+v\n", user)Il codice di interrogazione sopra è equivalente a
db.users.findOne({
address: "usa"
})Output del risultato
{Name:jack Age:18 Address:usa}Interrogazione multipla
type User struct {
Name string `bson:"name"`
Age int `bson:"age"`
Address string `bson:"address"`
}
var users []User
cursor, err := client.Database("user"). // Seleziona database
Collection("users"). // Seleziona collection
Find(ctx, bson.D{}) // Condizione di 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({})Output
[{Name:jack Age:18 Address:usa} {Name:mike Age:12 Address:} {Name:jenny Age:14 Address:}]Quando si costruiscono condizioni di interrogazione, è possibile utilizzare anche 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"). // Seleziona database
Collection("users"). // Seleziona collection
Find(ctx, bson.D{}, find) // Condizione di 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)Output
[{Name:mike Age:12 Address:}]Creare documenti
Esempio ufficiale di creazione: mongo-go-driver/examples/documentation_examples/examples.go at master · mongodb/mongo-go-driver (github.com)
Di seguito è riportato un esempio di creazione di 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)Dopo la creazione riuscita, verrà restituito l'ObjectID del documento
ObjectID("64c60fa01e2548d9e4de6cf4")Di seguito è riportato un esempio di creazione di più documenti
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)Dopo la creazione riuscita, viene restituito un gruppo di ObjectID
[ObjectID("64c610d5aec2618d6ca0b515") ObjectID("64c610d5aec2618d6ca0b516")]I due codici sopra sono equivalenti a db.users.insertOne e db.users.insertMany.
Aggiornare documenti
Esempio ufficiale di aggiornamento: mongo-go-driver/examples/documentation_examples/examples.go at master · mongodb/mongo-go-driver (github.com)
Di seguito è riportato un esempio di aggiornamento di un singolo documento, rinominare una persona di nome lili in 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"
},
})Output
&{MatchedCount:1 ModifiedCount:1 UpsertedCount:0 UpsertedID:<nil>}Di seguito è riportato un esempio di aggiornamento di più documenti, aggiornare l'indirizzo a cn per le persone di età 10
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)Oltre a utilizzare Update, mongo fornisce anche Replace. La differenza tra i due è che il primo aggiorna i campi del documento, mentre il secondo sostituisce direttamente il documento. Ad esempio, nel codice seguente, non sono più necessari operatori.
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)Allo stesso tempo, mongo fornisce anche FindOneAndUpdate e FindOneAndReplace per ottenere e aggiornare documenti. Come segue
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)Output
Name: Age:0 Address:cn}Questa operazione interroga prima il documento e poi lo modifica.
Eliminare documenti
Esempio ufficiale di eliminazione: mongo-go-driver/examples/documentation_examples/examples.go at master · mongodb/mongo-go-driver (github.com)
Di seguito è riportato un esempio di eliminazione di 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)Di seguito è riportato un esempio di eliminazione di più documenti
result, err := client.Database("user").Collection("users").DeleteMany(ctx, bson.D{
{"age", "10"},
})
if err != nil {
log.Panicln(err)
}
fmt.Println(result.DeletedCount)Aggregazione
Esempio ufficiale di aggregazione: mongo-go-driver/examples/documentation_examples/examples.go at master · mongodb/mongo-go-driver (github.com)
L'operazione di aggregazione utilizza il tipo mongo.Pipeline, la cui essenza è []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)Output
[{lili 20 uk} {kak 30 uk}]Questa operazione di aggregazione corrisponde a trovare tutti gli utenti con address uguale a uk, quindi ordinare per età.
