-
Notifications
You must be signed in to change notification settings - Fork 51
3. Using Mongo DB
Mahir edited this page Jul 23, 2022
·
3 revisions
Endpoints:
Add a new address: [HTTP POST] http://localhost:1200/api/v1/new-address
Body:
{
"person":"",
"street_name":"",
"house_number":"",
"postal_code":"",
"county":"",
"city":"",
"state":"",
"country":""
}
Find the address of a person: [HTTP GET] http://localhost:1200/api/v1/search-address/:name
Get a list of all records: [HTTP GET] http://localhost:1200/api/v1/all-addresses
This is a continuation of 1. RESTful API: Hello world project.
- Create a file
addresses.go
insidecontroller
folder - Write
Address
struct - Write a function
MongoCreateAddress
toaddresses.go
file - Write a function
MongoGetAll
toaddresses.go
file - Write a function
MongoGetAddress
toaddresses.go
file
package controller
import (
"context"
"net/http"
"reflect"
"strings"
"time"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"github.com/gin-gonic/gin"
"github.com/pilinux/gorest/database"
"github.com/pilinux/gorest/lib/renderer"
)
// Address - struct for saving addresses
type Address struct {
ID primitive.ObjectID `json:"id" bson:"_id"`
Person string `json:"person,omitempty" bson:"person,omitempty"`
StreetName string `json:"street_name,omitempty" bson:"street_name,omitempty"`
HouseNumber string `json:"house_number,omitempty" bson:"house_number,omitempty"`
PostalCode string `json:"postal_code,omitempty" bson:"postal_code,omitempty"`
County string `json:"county,omitempty" bson:"county,omitempty"`
City string `json:"city,omitempty" bson:"city,omitempty"`
State string `json:"state,omitempty" bson:"state,omitempty"`
Country string `json:"country,omitempty" bson:"country,omitempty"`
}
// MongoCreateAddress - create one document
func MongoCreateAddress(c *gin.Context) {
data := Address{}
if err := c.ShouldBindJSON(&data); err != nil {
renderer.Render(c, gin.H{"msg": "bad request"}, http.StatusBadRequest)
return
}
// remove all leading and trailing white spaces
data = trimSpace(data)
if data.isEmpty() {
renderer.Render(c, gin.H{"msg": "empty body"}, http.StatusBadRequest)
return
}
if len(data.Person) == 0 {
renderer.Render(c, gin.H{"msg": "person name is required"}, http.StatusBadRequest)
return
}
// generate a new ObjectID
data.ID = primitive.NewObjectID()
client := database.GetMongo()
db := client.Database("book") // set database name
collection := db.Collection("addresses") // set collection name
// set max TTL
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
// insert one document
_, err := collection.InsertOne(ctx, data)
if err != nil {
renderer.Render(c, gin.H{"msg": "internal server error"}, http.StatusInternalServerError)
return
}
renderer.Render(c, data, http.StatusCreated)
}
// MongoGetAll - get all documents
func MongoGetAll(c *gin.Context) {
client := database.GetMongo()
db := client.Database("book") // set database name
collection := db.Collection("addresses") // set collection name
// set max TTL
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
data := []Address{}
err := collection.Find(ctx, bson.M{}).All(&data)
if err != nil {
renderer.Render(c, gin.H{"msg": "internal server error"}, http.StatusInternalServerError)
return
}
if len(data) == 0 {
renderer.Render(c, gin.H{"msg": "no record found"}, http.StatusNotFound)
return
}
renderer.Render(c, data, http.StatusOK)
}
// MongoGetAddress - find the address of a person
func MongoGetAddress(c *gin.Context) {
name := strings.TrimSpace(c.Params.ByName("name"))
if len(name) == 0 {
renderer.Render(c, gin.H{"msg": "person name cannot be empty"}, http.StatusBadRequest)
return
}
client := database.GetMongo()
db := client.Database("book") // set database name
collection := db.Collection("addresses") // set collection name
// set max TTL
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
data := []Address{}
err := collection.Find(ctx, bson.M{"person": name}).All(&data)
if err != nil {
renderer.Render(c, gin.H{"msg": "internal server error"}, http.StatusInternalServerError)
return
}
if len(data) == 0 {
renderer.Render(c, gin.H{"msg": "no record found"}, http.StatusNotFound)
return
}
renderer.Render(c, data, http.StatusOK)
}
// trimSpace - remove all leading and trailing white spaces
func trimSpace(address Address) Address {
address.Person = strings.TrimSpace(address.Person)
address.StreetName = strings.TrimSpace(address.StreetName)
address.HouseNumber = strings.TrimSpace(address.HouseNumber)
address.PostalCode = strings.TrimSpace(address.PostalCode)
address.County = strings.TrimSpace(address.County)
address.City = strings.TrimSpace(address.City)
address.State = strings.TrimSpace(address.State)
address.Country = strings.TrimSpace(address.Country)
return address
}
// isEmpty - check empty struct
func (s Address) isEmpty() bool {
return reflect.DeepEqual(s, Address{})
}
- Update the
main
function inmain.go
file
package main
import (
"fmt"
"myapi/controller"
"github.com/gin-gonic/gin"
"github.com/pilinux/gorest/config"
"github.com/pilinux/gorest/database"
"github.com/pilinux/gorest/lib/middleware"
)
var configure = config.Config()
func main() {
if configure.Database.MongoDB.Activate == "yes" {
// Initialize MONGO client
if _, err := database.InitMongo(); err != nil {
fmt.Println(err)
return
}
}
router, err := SetupRouter()
if err != nil {
fmt.Println(err)
return
}
err = router.Run(":" + configure.Server.ServerPort)
if err != nil {
fmt.Println(err)
return
}
}
// SetupRouter ...
func SetupRouter() (*gin.Engine, error) {
router := gin.Default()
router.Use(middleware.CORS(
configure.Security.CORS.Origin,
configure.Security.CORS.Credentials,
configure.Security.CORS.Headers,
configure.Security.CORS.Methods,
configure.Security.CORS.MaxAge,
))
// For gorest <= v1.4.5
// router.Use(middleware.CORS())
// API:v1
v1 := router.Group("/api/v1/")
{
v1.GET("greetings", controller.Greetings)
if configure.Database.MongoDB.Activate == "yes" {
v1.POST("new-address", controller.MongoCreateAddress)
v1.GET("search-address/:name", controller.MongoGetAddress)
v1.GET("all-addresses", controller.MongoGetAll)
}
}
return router, nil
}
- Rename the file from
.env.sample
to.env
and modify the following lines:
APP_PORT=1200
ACTIVATE_MONGO=yes
# For MongoDB Atlas
# MONGO_URI=mongodb+srv://<username>:<password>@<cluster>.<subdomain>.mongodb.net/<cluster>?retryWrites=true&w=majority
# For standard connection on the local machine with auth
# MONGO_URI=mongodb://<username>:<password>@<IP>:<PORT>/?retryWrites=true&w=majority
- Build and start the app
go mod tidy -compat=1.17
go build
chmod +x myapi
./myapi
myapi
│--- main.go
│--- go.mod
│--- go.sum
│--- .env
│
└─── controller
│ └--- greetings.go
│ └--- addresses.go