This is a creation in Article, where the information may have evolved or changed.
- Using the Couchbase database in the Go web App
- Body
- Create a new project with a dependency packet
- Configuring Couchbase Services for Golang Engineering
- Designing RESTful Web Apps
- Conclusion
- Words
Using the Couchbase database in the Go web App
Date: 2016-08-05
Author: Nic Raboy
Original: https://www.thepolyglotdeveloper.com/2016/08/using-couchbase-server-golang-web-application/?utm_source= Tuicool&utm_medium=referral
A Flower and a world
Date: 2016-09-11
Typography: The Mark Flying Elephant (Https://maxiang.io)
Translation Preface
I translate according to the original text, in the process of feeling some common words difficult to express with simple words, understand that translation is not easy.
If there is any improper, please advise, I will be updated in time.
In addition, I also attached the new words to the text, after the main translation of the technical articles on the Go language, mainly short-based.
Body
Not long ago I wrote an article about how to build a restful API with the go language, but that article used only analog data rather than a real database. What if you use a real database in the go language? What database to use, or more importantly, which type of database to choose? Most APIs are transmitted in JSON format, so the same format is used for data storage. This means that the relational database may not be available. In contrast, NoSQL data works well for restful APIs. In a database that stores data in JSON format, it is popular to have an open-source database called Couchbase.
Let's look at the use of couchbase in the go language to develop restful web apps.
The previous article is the basis of this article example, so if you have not seen it, I highly recommend you to see.
If you don't go and see what I'm saying here, you may be confused.
Also, assume that the go language is installed and configured on your machine.
Create a new project with a dependency packet
For simplicity's sake, we'll create a new project. Using the (Mac and Linux) terminal or the command line (Windows), execute the following statement
Create a new Go project
$GOPATH/src/github.com/nraboy/cbproject
In fact, I have already created the above directory with the command, and if your system doesn't take effect, create it manually.
In the project catalog, there is a file in Main.go, which is also the only one in the work. Before you start coding, it's a good idea to download a dependency package in your project.
At the command line or terminal, do the following:
Get the extended dependency package
go get github.com/satori/go.uuidgo get github.com/couchbase/gocbgo get github.com/gorilla/mux
The dependency package contains a package that generates a UUID value, which is used to generate the IDs for the document; The SDK for Couchbase Go, a mux to increase the routing capability of the HTTP server.
Configuring Couchbase Services for Golang Engineering
Determine if the Couchbase configuration is available before you begin coding. Don't say how to install couchbase here. If you're using a Mac, Linux, or Windows machine, you can take a look at getting started with the installation tutorial. Now configure a bucket name in our app that can store NoSQL documents.
Now the goal is to create a couchbase bucket name named Restful-sample for the application, which has an appropriate index for executing the N1QL query.
In Couchbase's administrator interface, select Data Buckets, and then select Create New Data Bucket. Give the bucket a name and define the size of a storage space.
Create a bucket in couchbase
Next, I'll create an index for the new bucket.
When it comes to creating an index, there are a number of ways to achieve it. If Couchbase 4.5 or above, you can use the query Workbench. Execute the following query in Query Workbench:
Create a primary index for N1QL queries
CREATE PRIMARY INDEX onrestful-sampleUSING GSI;
Use N1QL to have at least one index. A more complex index than I have shown here will make the query faster.
Creating a primary index in Couchbase
If you do not have couchbase4.5 or higher installed, another method is to create an index. You can use Couchbase Query Shell (CBQ), which comes with Couchbase 4.0 or higher. Information about how to use these can be accessed here. can be used in Query workbench, or in the shell.
Here, the focus is on practical applications.
Designing RESTful Web Apps
Once the above configuration is done, you can write the code. This app has five basic sides to handle information about "people".
In the project $GOPATH/src/github.com/nraboy/cbproject/main.go file, add the following code:
$GOPATH/src/github.com/nraboy/cbproject/main.go
package main import ( "encoding/json" "log" "net/http" "github.com/couchbase/gocb" "github.com/gorilla/mux" "github.com/satori/go.uuid" ) type Person struct {
ID string `json:"id,omitempty"` Firstname string `json:"firstname,omitempty"` Lastname string `json:"lastname,omitempty"` Email string `json:"email,omitempty"` } type N1qlPerson struct {
Person Person `json:"person"` } var bucket *gocb.Bucket func GetPersonEndpoint(w http.ResponseWriter, req *http.Request) { var n1qlParams []interface{}
query := gocb.NewN1qlQuery("SELECT * FROM `restful-sample` AS person WHERE META(person).id = $1")
params := mux.Vars(req)
n1qlParams = append(n1qlParams, params["id"])
rows, _ := bucket.ExecuteN1qlQuery(query, n1qlParams) var row N1qlPerson
rows.One(&row)
json.NewEncoder(w).Encode(row.Person)
} func GetPeopleEndpoint(w http.ResponseWriter, req *http.Request) { var person []Person
query := gocb.NewN1qlQuery("SELECT * FROM `restful-sample` AS person")
rows, _ := bucket.ExecuteN1qlQuery(query, nil) var row N1qlPerson for rows.Next(&row) {
person = append(person, row.Person)
}
json.NewEncoder(w).Encode(person)
} func CreatePersonEndpoint(w http.ResponseWriter, req *http.Request) { var person Person var n1qlParams []interface{}
_ = json.NewDecoder(req.Body).Decode(&person)
query := gocb.NewN1qlQuery("INSERT INTO `restful-sample` (KEY, VALUE) VALUES ($1, {'firstname': $2, 'lastname': $3, 'email': $4})")
n1qlParams = append(n1qlParams, uuid.NewV4().String())
n1qlParams = append(n1qlParams, person.Firstname)
n1qlParams = append(n1qlParams, person.Lastname)
n1qlParams = append(n1qlParams, person.Email)
_, err := bucket.ExecuteN1qlQuery(query, n1qlParams) if err != nil {
w.WriteHeader(401)
w.Write([]byte(err.Error())) return }
json.NewEncoder(w).Encode(person)
} func UpdatePersonEndpoint(w http.ResponseWriter, req *http.Request) { var person Person var n1qlParams []interface{}
_ = json.NewDecoder(req.Body).Decode(&person)
query := gocb.NewN1qlQuery("UPDATE `restful-sample` USE KEYS $1 SET firstname = $2, lastname = $3, email = $4")
params := mux.Vars(req)
n1qlParams = append(n1qlParams, params["id"])
n1qlParams = append(n1qlParams, person.Firstname)
n1qlParams = append(n1qlParams, person.Lastname)
n1qlParams = append(n1qlParams, person.Email)
_, err := bucket.ExecuteN1qlQuery(query, n1qlParams) if err != nil {
w.WriteHeader(401)
w.Write([]byte(err.Error())) return }
json.NewEncoder(w).Encode(person)
} func DeletePersonEndpoint(w http.ResponseWriter, req *http.Request) { var n1qlParams []interface{}
query := gocb.NewN1qlQuery("DELETE FROM `restful-sample` AS person WHERE META(person).id = $1")
params := mux.Vars(req)
n1qlParams = append(n1qlParams, params["id"])
_, err := bucket.ExecuteN1qlQuery(query, n1qlParams) if err != nil {
w.WriteHeader(401)
w.Write([]byte(err.Error())) return }
json.NewEncoder(w).Encode(&Person{})
} func main() {
router := mux.NewRouter()
cluster, _ := gocb.Connect("couchbase://localhost")
bucket, _ = cluster.OpenBucket("restful-sample", "")
router.HandleFunc("/people", GetPeopleEndpoint).Methods("GET")
router.HandleFunc("/people/{id}", GetPersonEndpoint).Methods("GET")
router.HandleFunc("/people", CreatePersonEndpoint).Methods("PUT")
router.HandleFunc("/people/{id}", UpdatePersonEndpoint).Methods("POST")
router.HandleFunc("/people/{id}", DeletePersonEndpoint).Methods("DELETE")
log.Fatal(http.ListenAndServe(":12345", router))
}
There's a lot of functionality in the code above, and it's a good idea to take it apart.
First, we import a variety of dependency packages, which are mentioned earlier. With the package contained in this project, we can define two structures, one representing the JSON data, and we use it to work. The person structure contains the necessary information for the person, which will present the database in the form of JSON. When querying data, the result set is presented as an object of the parent JSON, which is required for the N1qlperson structure. The query results look like this:
JSON Data from Queries
{
"person": {
"id": "1234",
"firstname": "Nic",
"lastname": "Raboy",
"email": "nic@test.com" } }
In this structure, pay attention to the use of omitempty tags. This means that if a property is an empty value, it will not appear in the JSON results.
Before jumping to the end function, do the following:
$GOPATH/src/github.com/nraboy/cbproject/main.go
var bucket *gocb.Bucket
This bucket variable is defined outside the main function and is a global variable. It is used when querying data and opening couchbase buckets.
Jump to the main function of the project:
$GOPATH/src/github.com/nraboy/cbproject/main.go
func main() {
router := mux.NewRouter()
cluster, _ := gocb.Connect("couchbase://localhost")
bucket, _ = cluster.OpenBucket("restful-sample", "")
router.HandleFunc("/people", GetPeopleEndpoint).Methods("GET")
router.HandleFunc("/people/{id}", GetPersonEndpoint).Methods("GET")
router.HandleFunc("/people", CreatePersonEndpoint).Methods("PUT")
router.HandleFunc("/people/{id}", UpdatePersonEndpoint).Methods("POST")
router.HandleFunc("/people/{id}", DeletePersonEndpoint).Methods("DELETE")
log.Fatal(http.ListenAndServe(":12345", router))
}
The main function above defines the routing of the application and establishes a connection to the Couchbase cluster. In this case, the Couchbase cluster is running locally on our machine. When a couchbase cluster connection is established, a bucket can be opened. Here This bucket is called the restful-sample.
There are five different routes here. One is to get all the documents, one to get a single document, one to create a document, one to update, and the last to delete. Note that each of these routes uses get, PUT, POST, or DELETE. Let's look at each end function that matches it.
$GOPATH/src/github.com/nraboy/cbproject/main.go
func GetPersonEndpoint(w http.ResponseWriter, req *http.Request) { var n1qlParams []interface{}
query := gocb.NewN1qlQuery("SELECT * FROM `restful-sample` AS person WHERE META(person).id = $1")
params := mux.Vars(req)
n1qlParams = append(n1qlParams, params["id"])
rows, _ := bucket.ExecuteN1qlQuery(query, n1qlParams) var row N1qlPerson
rows.One(&row)
json.NewEncoder(w).Encode(row.Person)
}
The Getpersonendpoint function above takes a single-person record from the database. The ID in the meta-information is compared to the ID from the routing request. This query is a parameterized query that prevents SQL injection. We return the JSON data, which is only the structure of the person, not the entire N1plperson structure.
$GOPATH/src/github.com/nraboy/cbproject/main.go
func GetPeopleEndpoint(w http.ResponseWriter, req *http.Request) { var person []Person
query := gocb.NewN1qlQuery("SELECT * FROM `restful-sample` AS person")
rows, _ := bucket.ExecuteN1qlQuery(query, nil) var row N1qlPerson for rows.Next(&row) {
person = append(person, row.Person)
}
json.NewEncoder(w).Encode(person)
}
The above Getpeopleendpoint function is similar to the previous one, but this time the result is expected to be a slice rather than a single structure.
Create, update, and delete functions are almost as basic as above, making maintenance and understanding easy.
At this point, the application can run. It can be tested with curl, postman, and the Web browser does not provide ready-made tools to test put, POST, or DELETE.
Conclusion
You just saw that by using Couchbase as a NoSQL database, the previous example of the RESTful API go language was used in more depth. When using the Couchbase database, we use a class SQL query called N1QL to query the data, which makes coding easier and also reduces many potential syntax errors.
Words
- When it comes to doing
- Out of the The by
- At this point
- A lot going on
- Particular a certain
- Go with
- Meta information
- Being compared agains
- Prevent SQL Injection
- Out of the box
- Potential
- Mock data
- Make sense to