Para agentes de IA: um índice de documentação está disponível em https://www.mongodb.com/pt-br/docs/llms.txt — as versões de markdown de todas as páginas estão disponíveis anexando .md a qualquer caminho de URL.

Tutorial: Criar um Aplicativo da Web com o Driver Go e o Gi

Este tutorial mostra como criar um aplicativo web usando o MongoDB driver Go e o framework web Gin.

O Gi é um framework web rápido e leve para Go. Seu design mínima e modular o torna ideal para construir servidores web, APIs e microsserviços.

Neste tutorial, você pode aprender como criar um aplicativo da web com os seguintes pontos de extremidade que se conectam a um banco de dados MongoDB:

  • Um ponto de extremidade para recuperar todos os filmes de uma coleção

  • Um ponto de extremidade para recuperar um único filme por ID

  • Um ponto de extremidade para executar operações de agregação na coleção movies

O tutorial utiliza a coleção movies no banco de dados sample_mflix a partir do conjunto de dados de amostra do Atlas. Para aprender como criar um cluster MongoDB Atlas gratuito e carregar os conjuntos de dados de amostra, consulte o Get Started with Atlas guia.

Antes de iniciar este tutorial, verifique se você tem o seguinte:

  • Go instalado em sua máquina de desenvolvimento

  • Uma implantação MongoDB. Você pode utilizar um cluster MongoDB Atlas gratuito para este tutorial. Para mais informações, consulte o guia Iniciar com Atlas.

  • Uma ferramenta para testar sua API, como curl ou Postman.

1

Crie um novo diretório para seu projeto e navegue até ele:

mkdir mflixcd mflix

Inicialize um novo módulo Go para gerenciar as dependências do seu projeto :

go mod init mflix
2

Instale as dependências necessárias para seu projeto:

go get github.com/gin-gonic/gingo get go.mongodb.org/mongo-driver/v2/mongo
1

Crie um arquivo main.go no diretório do projeto e adicione o seguinte código para configurar um aplicativo Gin básico:

package main import ( "log" "github.com/gin-gonic/gin") func main() { r := gin.Default() r.GET("/", func(c *gin.Context) { c.JSON(200, gin.H{ "message": "Hello World", }) }) if err := r.Run(); err != nil { log.Fatal("Failed to start server:", err) }}
2

Execute o seguinte código para testar se seu aplicativo básico está funcionando:

go run main.go

Navegue até http://localhost:8080 em seu navegador da web para ver uma resposta JSON com a mensagem "Hello World".

Atualize seu arquivo main.go para se conectar ao MongoDB. Substitua o código existente pelo seguinte código para se conectar à sua implantação do MongoDB :

package main import ( "context" "log" "github.com/gin-gonic/gin" "go.mongodb.org/mongo-driver/v2/mongo" "go.mongodb.org/mongo-driver/v2/mongo/options") // Replace with your MongoDB connection stringconst uri = "<connection-string>" func main() { // Connects to MongoDB serverAPI := options.ServerAPI(options.ServerAPIVersion1) opts := options.Client().ApplyURI(uri).SetServerAPIOptions(serverAPI) client, err := mongo.Connect(opts) if err != nil { log.Fatal("Could not connect to MongoDB:", err) } // Ensures the client disconnects when main exits defer func() { if err := client.Disconnect(context.TODO()); err != nil { log.Fatal("Error disconnecting from MongoDB:", err) } }() // Pings the database to verify connection if err := client.Ping(context.TODO(), nil); err != nil { log.Fatal("Could not ping MongoDB:", err) } r := gin.Default() r.GET("/", func(c *gin.Context) { c.JSON(200, gin.H{ "message": "Hello World", }) }) if err := r.Run(); err != nil { log.Fatal("Failed to start server:", err) }}

Substitua o espaço reservado <connection-string> por sua string de conexão real do MongoDB . Para saber mais sobre como obter sua string de conexão, consulte o Conectar a um cluster guia.

Agora, você pode adicionar três pontos de extremidade para interação com os dados do filme. Atualize seu arquivo main.go para incluir as importações e implementações de pontos de extremidade necessárias.

1

Adicione as importações necessárias no topo do seu arquivo:

import ( "context" "log" "net/http" "github.com/gin-gonic/gin" "go.mongodb.org/mongo-driver/v2/bson" "go.mongodb.org/mongo-driver/v2/mongo" "go.mongodb.org/mongo-driver/v2/mongo/options")
2

Adicione os seguintes manipuladores de rota após sua função connectToMongoDB:

// GET /movies - Retrieves all moviesfunc getMovies(c *gin.Context, client *mongo.Client) { // Find all movies in the collection cursor, err := client.Database("sample_mflix").Collection("movies").Find(c.Request.Context(), bson.D{}) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } defer cursor.Close(c.Request.Context()) // Decodes all results var movies []bson.D if err = cursor.All(c.Request.Context(), &movies); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } // Returns the movies c.JSON(http.StatusOK, movies)} // GET /movies/:id - Retrieves a movie by IDfunc getMovieByID(c *gin.Context, client *mongo.Client) { // Gets the movie ID from the URL parameter as a string idStr := c.Param("id") // Converts string ID to MongoDB ObjectID id, err := bson.ObjectIDFromHex(idStr) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid movie ID format"}) return } // Finds the movie by ObjectID var movie bson.D err = client.Database("sample_mflix").Collection("movies").FindOne(c.Request.Context(), bson.D{{"_id", id}}).Decode(&movie) if err != nil { if err == mongo.ErrNoDocuments { c.JSON(http.StatusNotFound, gin.H{"error": "Movie not found"}) return } c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } // Returns the movie c.JSON(http.StatusOK, movie)} // POST /movies/aggregations - Runs aggregation pipelinefunc aggregateMovies(c *gin.Context, client *mongo.Client) { // Gets aggregation pipeline from request body var pipeline interface{} if err := c.ShouldBindJSON(&pipeline); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid aggregation pipeline"}) return } // Executes the aggregation pipeline cursor, err := client.Database("sample_mflix").Collection("movies").Aggregate(c.Request.Context(), pipeline) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } defer cursor.Close(c.Request.Context()) // Decodes the results var result []bson.D if err = cursor.All(c.Request.Context(), &result); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } // Returns the aggregation result c.JSON(http.StatusOK, result)}
3

Atualize sua função main para registrar as novas rotas:

func main() { // Connects to MongoDB serverAPI := options.ServerAPI(options.ServerAPIVersion1) opts := options.Client().ApplyURI(uri).SetServerAPIOptions(serverAPI) client, err := mongo.Connect(opts) if err != nil { log.Fatal("Could not connect to MongoDB:", err) } // Ensures the client disconnects when main exits defer func() { if err := client.Disconnect(context.TODO()); err != nil { log.Fatal("Error disconnecting from MongoDB:", err) } }() // Pings the database to verify connection if err := client.Ping(context.TODO(), nil); err != nil { log.Fatal("Could not ping MongoDB:", err) } r := gin.Default() r.GET("/", func(c *gin.Context) { c.JSON(200, gin.H{ "message": "Hello World", }) }) // Registers movie endpoints r.GET("/movies", func(c *gin.Context) { getMovies(c, client) }) r.GET("/movies/:id", func(c *gin.Context) { getMovieByID(c, client) }) r.POST("/movies/aggregations", func(c *gin.Context) { aggregateMovies(c, client) }) if err := r.Run(); err != nil { log.Fatal("Failed to start server:", err) }}

Você pode testar os pontos de extremidade criados para garantir que funcionem conforme o esperado.

Reinicie seu servidor e navegue até http://localhost:8080/movies em seu navegador da web. Você deverá ver uma resposta JSON contendo uma array de filmes do conjunto de dados de amostra.

Para testar o ponto de extremidade de filme único, copie um valor _id da resposta do filme e navegue até http://localhost:8080/movies/{id}.

Por exemplo, se você navegar para http://localhost:8080/movies/573a1390f29313caabcd42e8, a resposta no navegador será semelhante ao seguinte:

{ "_id": "573a1390f29313caabcd42e8", "awards": { "wins": 1, "nominations": 0, "text": "1 win." }, "cast": [ "A.C. Abadie", "Gilbert M. 'Broncho Billy' Anderson", "George Barnes", "Justus D. Barnes" ], "countries": [ "USA" ], "directors": [ "Edwin S. Porter" ], "fullplot": "Among the earliest existing films in American cinema - notable as the first film that presented a narrative story to tell - it depicts a group of cowboy outlaws who hold up a train and rob the passengers. They are then pursued by a Sheriff's posse. Several scenes have color included - all hand tinted.", "genres": [ "Short", "Western" ]," ....}

Para testar o ponto de extremidade de agregação, é necessário fazer uma solicitação publicação. Você pode usar uma ferramenta como curl ou Postman para enviar uma solicitação com um pipeline de agregação no corpo da solicitação.

O exemplo de agregação a seguir conta filmes de comedia por ano:

[ {"$match": {"genres": "Comedy"}}, {"$group": { "_id": "$year", "count": {"$sum": 1} }}, {"$sort": {"count": -1}}]

Execute o seguinte código no seu terminal para testar esse ponto de extremidade com curl:

curl -X POST http://localhost:8080/movies/aggregations \ -H "Content-Type: application/json" \ -d '[ {"$match": {"genres": "Comedy"}}, {"$group": {"_id": "$year", "count": {"$sum": 1}}}, {"$sort": {"count": -1}} ]'

Aviso

O ponto de extremidade de agregação neste tutorial permite que os usuários executem qualquer pipeline de agregação. Em um ambiente de produção, você deve limitar os tipos de operações e validar a entrada para evitar possíveis problemas de segurança ou de desempenho.

O seguinte arquivo mostra o código completo do seu aplicativo da web:

package main import ( "context" "log" "net/http" "github.com/gin-gonic/gin" "go.mongodb.org/mongo-driver/v2/bson" "go.mongodb.org/mongo-driver/v2/mongo" "go.mongodb.org/mongo-driver/v2/mongo/options") // Replace with your MongoDB connection stringconst uri = "YOUR-CONNECTION-STRING-HERE" func main() { // Connects to MongoDB serverAPI := options.ServerAPI(options.ServerAPIVersion1) opts := options.Client().ApplyURI(uri).SetServerAPIOptions(serverAPI) client, err := mongo.Connect(opts) if err != nil { log.Fatal("Could not connect to MongoDB:", err) } // Ensures the client disconnects when main exits defer func() { if err := client.Disconnect(context.TODO()); err != nil { log.Fatal("Error disconnecting from MongoDB:", err) } }() // Pings the database to verify connection if err := client.Ping(context.TODO(), nil); err != nil { log.Fatal("Could not ping MongoDB:", err) } r := gin.Default() r.GET("/", func(c *gin.Context) { c.JSON(200, gin.H{ "message": "Hello World", }) }) // Registers movie endpoints r.GET("/movies", func(c *gin.Context) { getMovies(c, client) }) r.GET("/movies/:id", func(c *gin.Context) { getMovieByID(c, client) }) r.POST("/movies/aggregations", func(c *gin.Context) { aggregateMovies(c, client) }) if err := r.Run(); err != nil { log.Fatal("Failed to start server:", err) }} // GET /movies - Retrieves all moviesfunc getMovies(c *gin.Context, client *mongo.Client) { // Find all movies in the collection cursor, err := client.Database("sample_mflix").Collection("movies").Find(c.Request.Context(), bson.D{}) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } defer cursor.Close(c.Request.Context()) // Decodes all results var movies []bson.D if err = cursor.All(c.Request.Context(), &movies); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } // Returns the movies c.JSON(http.StatusOK, movies)} // GET /movies/:id - Retrieves a movie by IDfunc getMovieByID(c *gin.Context, client *mongo.Client) { // Gets the movie ID from the URL parameter as a string idStr := c.Param("id") // Converts string ID to MongoDB ObjectID id, err := bson.ObjectIDFromHex(idStr) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid movie ID format"}) return } // Finds the movie by ObjectID var movie bson.D err = client.Database("sample_mflix").Collection("movies").FindOne(c.Request.Context(), bson.D{{"_id", id}}).Decode(&movie) if err != nil { if err == mongo.ErrNoDocuments { c.JSON(http.StatusNotFound, gin.H{"error": "Movie not found"}) return } c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } // Returns the movie c.JSON(http.StatusOK, movie)} // POST /movies/aggregations - Runs aggregation pipelinefunc aggregateMovies(c *gin.Context, client *mongo.Client) { // Gets aggregation pipeline from request body var pipeline interface{} if err := c.ShouldBindJSON(&pipeline); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid aggregation pipeline"}) return } // Executes the aggregation pipeline cursor, err := client.Database("sample_mflix").Collection("movies").Aggregate(c.Request.Context(), pipeline) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } defer cursor.Close(c.Request.Context()) // Decodes the results var result []bson.D if err = cursor.All(c.Request.Context(), &result); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } // Returns the aggregation result c.JSON(http.StatusOK, result)}

Agora você tem um aplicativo básico que demonstra o seguinte:

  • Configura um projeto Go com o framework web Gi e o driver Go.

  • Conecta-se a um banco de dados MongoDB usando o driver Go.

  • Implementa pontos de extremidade de API REST que executam operações MongoDB para localizar documentos, localizar um único documento e executar pipelines de agregação.

  • Lida com cenários comuns, como converter IDs de string em ObjectIDs.

  • Implementa o tratamento adequado de erros para operações de banco de dados .

Para desenvolver ainda mais seu aplicativo, considere as seguintes etapas a seguir:

  • Adicionar validação de entrada e limitação de solicitação para o ponto de extremidade de agregação

  • Implementar autenticação e autorização

  • Adicionar índices para melhorar o desempenho da query

Para saber mais sobre os conceitos deste tutorial, consulte os seguintes recursos: