Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

examples: adds crud example #368

Merged
merged 1 commit into from
Jul 24, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions examples/crud/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Go GraphQL CRUD example

Implementation create, read, update and delete on Go

To run the program, go to the directory
`cd examples/crud`

Run the example
`go run main.go`

## Create
`http://localhost:8080/product?query=mutation+_{create(name:"Inca Kola",info:"Inca Kola is a soft drink that was created in Peru in 1935 by British immigrant Joseph Robinson Lindley using lemon verbena (wiki)",price:1.99){id,name,info,price}}`

## Read
Get single product by id
`http://localhost:8080/product?query={product(id:1){name,info,price}}`

Get product list
`http://localhost:8080/product?query={list{id,name,info,price}}`

## Update
`http://localhost:8080/product?query=mutation+_{update(id:1,price:3.95){id,name,info,price}}`

## Delete
`http://localhost:8080/product?query=mutation+_{delete(id:1){id,name,info,price}}`
225 changes: 225 additions & 0 deletions examples/crud/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
package main

import (
"encoding/json"
"fmt"
"math/rand"
"net/http"
"time"

"github.com/graphql-go/graphql"
)

type Product struct {
ID int64 `json:"id"`
Name string `json:"name"`
Info string `json:"info,omitempty"`
Price float64 `json:"price"`
}

var products []Product

var productType = graphql.NewObject(
graphql.ObjectConfig{
Name: "Product",
Fields: graphql.Fields{
"id": &graphql.Field{
Type: graphql.Int,
},
"name": &graphql.Field{
Type: graphql.String,
},
"info": &graphql.Field{
Type: graphql.String,
},
"price": &graphql.Field{
Type: graphql.Float,
},
},
},
)

var queryType = graphql.NewObject(
graphql.ObjectConfig{
Name: "Query",
Fields: graphql.Fields{
/* Get (read) single product by id
http://localhost:8080/product?query={product(id:1){name,info,price}}
*/
"product": &graphql.Field{
Type: productType,
Description: "Get product by id",
Args: graphql.FieldConfigArgument{
"id": &graphql.ArgumentConfig{
Type: graphql.Int,
},
},
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
id, ok := p.Args["id"].(int)
if ok {
// Find product
for _, product := range products {
if int(product.ID) == id {
return product, nil
}
}
}
return nil, nil
},
},
/* Get (read) product list
http://localhost:8080/product?query={list{id,name,info,price}}
*/
"list": &graphql.Field{
Type: graphql.NewList(productType),
Description: "Get product list",
Resolve: func(params graphql.ResolveParams) (interface{}, error) {
return products, nil
},
},
},
})

var mutationType = graphql.NewObject(graphql.ObjectConfig{
Name: "Mutation",
Fields: graphql.Fields{
/* Create new product item
http://localhost:8080/product?query=mutation+_{create(name:"Inca Kola",info:"Inca Kola is a soft drink that was created in Peru in 1935 by British immigrant Joseph Robinson Lindley using lemon verbena (wiki)",price:1.99){id,name,info,price}}
*/
"create": &graphql.Field{
Type: productType,
Description: "Create new product",
Args: graphql.FieldConfigArgument{
"name": &graphql.ArgumentConfig{
Type: graphql.NewNonNull(graphql.String),
},
"info": &graphql.ArgumentConfig{
Type: graphql.String,
},
"price": &graphql.ArgumentConfig{
Type: graphql.NewNonNull(graphql.Float),
},
},
Resolve: func(params graphql.ResolveParams) (interface{}, error) {
rand.Seed(time.Now().UnixNano())
product := Product{
ID: int64(rand.Intn(100000)), // generate random ID
Name: params.Args["name"].(string),
Info: params.Args["info"].(string),
Price: params.Args["price"].(float64),
}
products = append(products, product)
return product, nil
},
},

/* Update product by id
http://localhost:8080/product?query=mutation+_{update(id:1,price:3.95){id,name,info,price}}
*/
"update": &graphql.Field{
Type: productType,
Description: "Update product by id",
Args: graphql.FieldConfigArgument{
"id": &graphql.ArgumentConfig{
Type: graphql.NewNonNull(graphql.Int),
},
"name": &graphql.ArgumentConfig{
Type: graphql.String,
},
"info": &graphql.ArgumentConfig{
Type: graphql.String,
},
"price": &graphql.ArgumentConfig{
Type: graphql.Float,
},
},
Resolve: func(params graphql.ResolveParams) (interface{}, error) {
id, _ := params.Args["id"].(int)
name, nameOk := params.Args["name"].(string)
info, infoOk := params.Args["info"].(string)
price, priceOk := params.Args["price"].(float64)
product := Product{}
for i, p := range products {
if int64(id) == p.ID {
if nameOk {
products[i].Name = name
}
if infoOk {
products[i].Info = info
}
if priceOk {
products[i].Price = price
}
product = products[i]
break
}
}
return product, nil
},
},

/* Delete product by id
http://localhost:8080/product?query=mutation+_{delete(id:1){id,name,info,price}}
*/
"delete": &graphql.Field{
Type: productType,
Description: "Delete product by id",
Args: graphql.FieldConfigArgument{
"id": &graphql.ArgumentConfig{
Type: graphql.NewNonNull(graphql.Int),
},
},
Resolve: func(params graphql.ResolveParams) (interface{}, error) {
id, _ := params.Args["id"].(int)
product := Product{}
for i, p := range products {
if int64(id) == p.ID {
product = products[i]
// Remove from product list
products = append(products[:i], products[i+1:]...)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is better to use something like Filtering without allocating when removing items within a loop, just as general recommendation.

productsUpdated := products[:0]
for _, p := range products {
  if int64(id) != p.ID {
    productsUpdated = append(productsUpdated, p)
  }
}

}
}

return product, nil
},
},
},
})

var schema, _ = graphql.NewSchema(
graphql.SchemaConfig{
Query: queryType,
Mutation: mutationType,
},
)

func executeQuery(query string, schema graphql.Schema) *graphql.Result {
result := graphql.Do(graphql.Params{
Schema: schema,
RequestString: query,
})
if len(result.Errors) > 0 {
fmt.Printf("errors: %v", result.Errors)
}
return result
}

func initProductsData(p *[]Product) {
product1 := Product{ID: 1, Name: "Chicha Morada", Info: "Chicha morada is a beverage originated in the Andean regions of Perú but is actually consumed at a national level (wiki)", Price: 7.99}
product2 := Product{ID: 2, Name: "Chicha de jora", Info: "Chicha de jora is a corn beer chicha prepared by germinating maize, extracting the malt sugars, boiling the wort, and fermenting it in large vessels (traditionally huge earthenware vats) for several days (wiki)", Price: 5.95}
product3 := Product{ID: 3, Name: "Pisco", Info: "Pisco is a colorless or yellowish-to-amber colored brandy produced in winemaking regions of Peru and Chile (wiki)", Price: 9.95}
*p = append(*p, product1, product2, product3)
}

func main() {
// Primary data initialization
initProductsData(&products)

http.HandleFunc("/product", func(w http.ResponseWriter, r *http.Request) {
result := executeQuery(r.URL.Query().Get("query"), schema)
json.NewEncoder(w).Encode(result)
})

fmt.Println("Server is running on port 8080")
http.ListenAndServe(":8080", nil)
}