Go Lang and MongoDB Web App MVC pattern Part 4

Introduction

This is Part 4 in the multiple-series tutorial “Go Lang and MongoDB Web App with MVC pattern.” In Part 3, you learned how to enable your web app to READ your MongoDB data correctly. Today, you’ll add the functionality to show just one record based on a “sku” variable’s value.

If you’re already familiar with how to add the code that enables you to display just a single record, and you want to skip the details, go The Code.

Prerequisite

  • Complete Parts 1 through 3 of the tutorial series “Go Lang and MongoDB App with MVC pattern.”

Retrieve a Single Record in MongoDB using Go Lang

  • Access the file main.go and use Go Lang to add the handle function to get just one MongoDB record:
 http.HandleFunc("/", index)
    http.HandleFunc("/products", model.Index)

    // handles the URL 'localhost:8080/product/show?sku=<sku>
    http.HandleFunc("/products/show", model.ShowProduct)


    http.ListenAndServe(":8080", nil)

http.ListenAndServe(":8080", nil)

Here’s an explanation of the code you just inputted above:

  • The controller contains the ShowProduct() function and that function receives the routed request.

Controller for Showing a MongoDB Single Record

  • Make a Go script for your Go Lang and MongoDB Web App with MVC pattern. This one will be for creating a function in the controller for the controller.go:
func ShowProduct(w http.ResponseWriter, r *http.Request) {
    if r.Method != "GET" {
        http.Error(w, http.StatusText(405), http.StatusMethodNotAllowed)
        return
    }

    pr, err := OneProduct(r)
    switch {
    case err == sql.ErrNoRows:
        http.NotFound(w, r)
        return
    case err != nil:
        http.Error(w, http.StatusText(500), http.StatusInternalServerError)
        return
    }

    config.TPL.ExecuteTemplate(w, "show_product.gohtml", pr)
}

The above code explained:

  • It searches for a “sku” value that the user forwarded. The value it’s looking for is in the variable “r”

  • The response is put into the “pr” variable. It is then be processed when it’s passed to the “show_product.gohtml” template.

The Model for Showing a MongoDB Record

  • Construct a new Model to make a MongoDB database record request:
func OneProduct(r *http.Request) (ProductCat, error) {
    pr := ProductCat{}
    sku := r.FormValue("sku")
    if sku == "" {
        return pr, errors.New("400. Bad Request.")
    }
    err := config.Product.Find(bson.M{"sku": sku}).One(&pr)
    if err != nil {
        return pr, err
    }
    return pr, nil
}

The code above for your Go Lang and MongoDB Web App with MVC pattern indicates that it uses the Find() method to look for a document in a MongoDB collection that has the same “sku” value variable. The One() helper method limits the search to just one document.

  • Change the link called View in index.gothml with this code:
<td><a class="action" href="/products/show?sku={{.Sku}}">View</a></td>

You created the code above to be able to pass the document’s “sku” value as a parameter URL. You used that same URL to perform the MongoDB database query.

Configuring the Front-end

  • Setup the front-end with a template for viewing the records you picked:
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Product Information</title>
    <link
      rel="stylesheet"
      href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
      integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm"
      crossorigin="anonymous"
    />
    <script
      src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
      integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"
      crossorigin="anonymous"
    ></script>
  </head>
  <body>
    <div class="container mb-6">
      <form class="mt-5">
        <h2>Products's Details</h2>
        <div class="form-group row">
          <label for="sku" class="col-sm-2 col-form-label">Sku</label>
          <div class="col-sm-10">
            <input
              type="text"
              class="form-control"
              id="sku"
              value="{{.Sku}}"
              disabled
            />
          </div>
        </div>
        <div class="form-group row">
          <label for="title" class="col-sm-2 col-form-label">Title</label>
          <div class="col-sm-10">
            <input
              type="text"
              class="form-control"
              id="title"
              value="{{.Title}}"
              disabled
            />
          </div>
        </div>
        <div class="form-group row">
          <label for="desciption" class="col-sm-2 col-form-label"
            >Description</label
          >
          <div class="col-sm-10">
            <input
              type="text"
              class="form-control"
              id="desciption"
              value="{{.Description}}"
              disabled
            />
          </div>
        </div>
        <div class="form-group row">
          <label for="quantity" class="col-sm-2 col-form-label">Quantity</label>
          <div class="col-sm-10">
            <input
              type="text"
              class="form-control"
              id="quantity"
              value="{{.Qty}}"
              disabled
            />
          </div>
        </div>
        <div class="form-group row">
          <label for="price" class="col-sm-2 col-form-label">Price</label>
          <div class="col-sm-10">
            <input
              type="text"
              class="form-control"
              id="price"
              value="{{.Pricing}}"
              disabled
            />
          </div>
        </div>

        <div class="form-group row">
          <div class="col-sm-10 offset-sm-2">
            <a class="btn btn-primary" href="/"> « Product Listing</a>
          </div>
        </div>
      </form>
    </div>
  </body>
</html>

NOTE: Notice the data structure in the Go Lang and MongoDB Web App with MVC pattern includes the “.” (dot) notations in the input type lines of code for the values “{{.Description}}”, etc.

  • Now at the terminal, test your application. Use the command with go run main.go:

  • Input the ‘localhost:8080/products’ URL in a browser tab.

  • Select the View action to view the desired record.

  • Your result should resemble one similar to this:

Conclusion

This concludes Part 4 of “Go Lang and MongoDB Web App with MVC pattern.” You added the functionality to your application that enables you to select just one record based on a “sku” variable’s value. It’s all about the end-user retrieving specific data in the fastest way possible. Use the coding techniques presented in this multiple-series tutorial often.

The Code

Here’s the entire code for the lesson in Part 4 of the Go Lang and MongoDB Web App with MVC pattern.

The main.go

 http.HandleFunc("/", index)
    http.HandleFunc("/products", model.Index)

    // handles the URL 'localhost:8080/product/show?sku=<sku>
    http.HandleFunc("/products/show", model.ShowProduct)


    http.ListenAndServe(":8080", nil)

http.ListenAndServe(":8080", nil)

The show_product.gohtml

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Product Information</title>
    <link
     rel="stylesheet"
     href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
     integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm"
     crossorigin="anonymous"
   />
    <script
     src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
     integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"
     crossorigin="anonymous"
   ></script>
  </head>
  <body>
    <div class="container mb-6">
      <form class="mt-5">
        <h2>Products's Details</h2>
        <div class="form-group row">
          <label for="sku" class="col-sm-2 col-form-label">Sku</label>
          <div class="col-sm-10">
            <input
             type="text"
             class="form-control"
             id="sku"
             value="{{.Sku}}"
             disabled
           />
          </div>
        </div>
        <div class="form-group row">
          <label for="title" class="col-sm-2 col-form-label">Title</label>
          <div class="col-sm-10">
            <input
             type="text"
             class="form-control"
             id="title"
             value="{{.Title}}"
             disabled
           />
          </div>
        </div>
        <div class="form-group row">
          <label for="desciption" class="col-sm-2 col-form-label"
           >Description</label
         >
          <div class="col-sm-10">
            <input
             type="text"
             class="form-control"
             id="desciption"
             value="{{.Description}}"
             disabled
           />
          </div>
        </div>
        <div class="form-group row">
          <label for="quantity" class="col-sm-2 col-form-label">Quantity</label>
          <div class="col-sm-10">
            <input
             type="text"
             class="form-control"
             id="quantity"
             value="{{.Qty}}"
             disabled
           />
          </div>
        </div>
        <div class="form-group row">
          <label for="price" class="col-sm-2 col-form-label">Price</label>
          <div class="col-sm-10">
            <input
             type="text"
             class="form-control"
             id="price"
             value="{{.Pricing}}"
             disabled
           />
          </div>
        </div>

        <div class="form-group row">
          <div class="col-sm-10 offset-sm-2">
            <a class="btn btn-primary" href="/"> « Product Listing</a>
          </div>
        </div>
      </form>
    </div>
  </body>
</html>

The models.go

func OneProduct(r *http.Request) (ProductCat, error) {
    pr := ProductCat{}
    sku := r.FormValue("sku")
    if sku == "" {
        return pr, errors.New("400. Bad Request.")
    }
    err := config.Product.Find(bson.M{"sku": sku}).One(&pr)
    if err != nil {
        return pr, err
    }
    return pr, nil
}

The handler.go

func ShowProduct(w http.ResponseWriter, r *http.Request) {
    if r.Method != "GET" {
        http.Error(w, http.StatusText(405), http.StatusMethodNotAllowed)
        return
    }

    pr, err := OneProduct(r)
    switch {
    case err == sql.ErrNoRows:
        http.NotFound(w, r)
        return
    case err != nil:
        http.Error(w, http.StatusText(500), http.StatusInternalServerError)
        return
    }

    config.TPL.ExecuteTemplate(w, "show_product.gohtml", pr)
}

Pilot the ObjectRocket Platform Free!

Try Fully-Managed CockroachDB, Elasticsearch, MongoDB, PostgreSQL (Beta) or Redis.

Get Started

Keep in the know!

Subscribe to our emails and we’ll let you know what’s going on at ObjectRocket. We hate spam and make it easy to unsubscribe.