Cómo usar MongoDB con Go

Esta sección del instructivo de Bookshelf muestra cómo la app de muestra almacena los datos persistentes en una base de datos de MongoDB.

Esta página forma parte de un instructivo de varias páginas. Para comenzar desde el principio y leer las instrucciones de configuración, visita la app de Bookshelf para Go.

Cómo ejecutar MongoDB en Google Compute Engine

Si no configuraste una instancia de Mongo, puedes crear una administrada que se ejecute sobre Google Cloud Platform mediante Atlas en GCP o mLab. Si prefieres usar una instancia de MongoDB sin administrar que se ejecute en Compute Engine, revisa la solución preconfigurada con implementación en un clic de Bitnami.

Para lograr el mejor rendimiento, asegúrate de que la instancia de MongoDB se aloje en Google Cloud Platform y que se ubique en la misma región de tu app.

De manera predeterminada, MongoDB usa el puerto 27017 para la comunicación. Una vez configurada la instancia de MongoDB, es posible que tengas que configurar las reglas de firewall para permitir el tráfico desde y hacia este puerto. Si necesitas instrucciones para las instancias que se ejecutan en Google Cloud Platform, consulta Uso de reglas de firewall.

Configuraciones

  1. Ve al directorio que contiene el código de muestra:

    Linux/macOS

    cd $GOPATH/src/github.com/GoogleCloudPlatform/golang-samples/getting-started/bookshelf
    

    Windows

    cd %GOPATH%\src\github.com\GoogleCloudPlatform\golang-samples\getting-started\bookshelf
    

  2. Abre config.go para editar.

  3. Borra los comentarios de las siguientes líneas:

    // var cred *mgo.Credential
    // DB, err = newMongoDB("localhost", cred)
    
  4. Reemplaza localhost por la dirección IP externa de tu instancia de MongoDB. Esta es la IP externa que anotaste en la sección anterior. También puedes ejecutar gcloud compute instances list para encontrar la dirección IP externa.

  5. Guarda y cierra config.go.

Cómo ejecutar la app en la máquina local

  1. Ejecuta la app para iniciar un servidor web local:

    cd app
    go run app.go auth.go template.go
    
  2. En el navegador web, ingresa la siguiente dirección:

    http://localhost:8080

Ahora puedes navegar por las páginas web de la app y agregar, editar y borrar libros.

Presiona Control + C para salir del servidor web local.

Cómo implementar la app en el entorno flexible de App Engine

  1. En el directorio app, ingresa el siguiente comando para implementar la muestra:

    gcloud app deploy
    
  2. En el navegador web, ingresa la siguiente dirección. Reemplaza [YOUR_PROJECT_ID] por el ID del proyecto:

    https://[YOUR_PROJECT_ID].appspot.com
    

Si actualizas tu app, podrás implementar la versión actualizada mediante el mismo comando que usaste para implementar la app por primera vez. La implementación nueva crea una versión nueva de tu app y la convierte a la versión predeterminada. Las versiones anteriores de la app se conservan, al igual que sus instancias de VM asociadas. Ten en cuenta que todas estas instancias de VM y versiones de la app son recursos facturables.

Para reducir costos, borra las versiones no predeterminadas de la app.

Para borrar una versión de una app, haz lo siguiente:

  1. In the GCP Console, go to the Versions page for App Engine.

    Go to the Versions page

  2. Select the checkbox for the non-default app version you want to delete.
  3. Click Delete to delete the app version.

Para obtener toda la información acerca de la limpieza de los recursos facturables, consulta la sección Limpieza en el paso final de este instructivo.

Estructura de la aplicación

El siguiente diagrama muestra cómo los componentes de la aplicación de muestra se conectan entre sí.

Proceso y estructura de la implementación de la app de Bookshelf

Cómo comprender el código

En esta sección se explica el código de la aplicación y su funcionamiento.

Cómo manejar los envíos de los usuarios con formularios

Cuando un usuario hace clic en Add Book (Agregar libro), el navegador lo lleva a /books/add y la función addFormHandler en app/app.go muestra un formulario donde el usuario puede agregar un libro:

r.Methods("GET").Path("/books/add").
	Handler(appHandler(addFormHandler))
// addFormHandler displays a form that captures details of a new book to add to
// the database.
func addFormHandler(w http.ResponseWriter, r *http.Request) *appError {
	return editTmpl.Execute(w, r, nil)
}

Imagen de un formulario para agregar y editar

El formulario incluye campos de entrada de texto para Title (Título), Author (Autor), Date Published (Fecha de publicación) y Description (Descripción), además de otros que se utilizan en otras secciones de este instructivo.

<form method="post" enctype="multipart/form-data" action="/books{{if .}}/{{.ID}}{{end}}">
  <div class="form-group">
    <label for="title">Title</label>
    <input class="form-control" name="title" id="title" value="{{.Title}}">
  </div>
  <div class="form-group">
    <label for="author">Author</label>
    <input class="form-control" name="author" id="author" value="{{.Author}}">
  </div>
  <div class="form-group">
    <label for="publishedDate">Date Published</label>
    <input class="form-control" name="publishedDate" id="publishedDate" value="{{.PublishedDate}}">
  </div>
  <div class="form-group">
    <label for="description">Description</label>
    <input class="form-control" name="description" id="description" value="{{.Description}}">
  </div>
  <div class="form-group">
    <label for="image">Cover Image</label>
    <input class="form-control" name="image" id="image" type="file">
  </div>
  <button class="btn btn-success">Save</button>
  <input type="hidden" name="imageURL" value="{{.ImageURL}}">
  <input type="hidden" name="createdBy" value="{{.CreatedBy}}">
  <input type="hidden" name="createdByID" value="{{.CreatedByID}}">
</form>

Cómo manejar los envíos de formularios

Cuando un usuario completa el formulario y hace clic en Save (Guardar), el siguiente código maneja la acción HTTP POST /books del formulario. El código inserta el nuevo libro en la base de datos mediante una llamada a la función bookshelf.DB.AddBook().

r.Methods("POST").Path("/books").
	Handler(appHandler(createHandler))
// createHandler adds a book to the database.
func createHandler(w http.ResponseWriter, r *http.Request) *appError {
	book, err := bookFromForm(r)
	if err != nil {
		return appErrorf(err, "could not parse book from form: %v", err)
	}
	id, err := bookshelf.DB.AddBook(book)
	if err != nil {
		return appErrorf(err, "could not save book: %v", err)
	}
	go publishUpdate(id)
	http.Redirect(w, r, fmt.Sprintf("/books/%d", id), http.StatusFound)
	return nil
}

La función AddBook, definida en db_mongo.go, realiza una operación Insert() para agregar los datos enviados por el usuario como un documento a la colección de MongoDB.

// AddBook saves a given book, assigning it a new ID.
func (db *mongoDB) AddBook(b *Book) (id int64, err error) {
	id, err = randomID()
	if err != nil {
		return 0, fmt.Errorf("mongodb: could not assign a new ID: %v", err)
	}

	b.ID = id
	if err := db.c.Insert(b); err != nil {
		return 0, fmt.Errorf("mongodb: could not add book: %v", err)
	}
	return id, nil
}

Cuando el usuario hace clic en Libros, el navegador lo lleva a la página /books y el método ListBooks muestra todos los libros en el almacén de datos.

La instrucción db.c.Find(nil) crea una consulta que selecciona todos los documentos de la colección. La consulta incluye .Sort("title"), que especifica que los resultados deben ordenarse alfabéticamente por título del libro.

La consulta se ejecuta mediante una llamada a All, que adjunta todos los documentos mostrados al segmento result.

// ListBooks returns a list of books, ordered by title.
func (db *mongoDB) ListBooks() ([]*Book, error) {
	var result []*Book
	if err := db.c.Find(nil).Sort("title").All(&result); err != nil {
		return nil, err
	}
	return result, nil
}
¿Te ha resultado útil esta página? Enviar comentarios: