GraphQL & DGraph with GO
1
James tan
@ Okestra Systems Sdn Bhd | https://okestra.co/ | james@okestra.co | 0123221812
2
Workflow management simplified
Let’s make GO fun!
With AI (soon)
What is GraphQL?
GraphQL is a query language for APIs and a runtime for fulfilling those queries
with your existing data.
3
Who uses GraphQL?
4
And more @ https://graphql.org/users/
Trusty REST
GET, POST, HEAD, DELETE, OPTIONS, PUT, TRACE, CONNECT
GET /pages
GET /pages/5
POST /pages
PUT /pages/5
DELETE /pages/5
Examples:
5
Why GraphQL
6
Multiple Round
Trip
7
● fetch /pages/1
● fetch /comments?pageID=1
● fetch /users/2
query page($id: Int) {
page(ID: $id) {
title
description
comments {
id
message
created_by {
id
name
}
}
}
}
REST:
GraphQL:
Multiple Round
Trip
8
● fetch /pages/1
● fetch /comments?pageID=1
● fetch /users/2
query page($id: Int) {
page(ID: $id) {
title
description
comments {
id
message
created_by {
id
name
}
}
}
announcements() {
edges {
node: {
id
title
message
}
}
}
REST:
GraphQL:
Over fetching data
9
● Frontend: fetch /pages
● Admin: fetch /pages
Frontend:
Admin:
title date
description
title date
description
...
ID title Created by Created on Published
1 Title here ... ... Yes
2 comments
5 comments
[
{ id: 1, title: “title”,
description: “...”,
created_at: “...”,
created_by: { name: “...” },
Comments_count: 2
}, …
]
REST Frontend & admin:
Over fetching data
10
Frontend:
Admin:
title date
description
title date
description
...
ID title Created by Created on Published
1 Title here ... ... Yes
2 comments
5 comments
query page($id: Int) {
page(ID: $id) {
title
description
Comment_count
…
}}
GraphQL frontend:
query page($id: Int) {
page(ID: $id) {
Title
…
}}
GraphQL admin:
Schema Documentation
11
Allow API Discovery and exploration
REST:
schema {
query: Query
mutation: Mutation
}
type Query {
user(email: String!): User
users(first: Int, after: String): UsersConnection!
}
type Mutation {
createUser(email: String!, password: String!): User
}
Implementing GraphQL
● graphql-go: An implementation of GraphQL for Go / Golang.
● graph-gophers/graphql-go: An active implementation of GraphQL in Golang (was
https://github.com/graph-gophers/graphql-go).
● GQLGen - Go generate based graphql server library.
● graphql-relay-go: A Go/Golang library to help construct a graphql-go server supporting
react-relay.
● machinebox/graphql: An elegant low-level HTTP client for GraphQL.
● samsarahq/thunder: A GraphQL implementation with easy schema building, live queries,
and batching
12
https://graphql.org/code/#go
Graphql-go
● minimal API
● support for context.Context
● support for the OpenTracing standard
● schema type-checking against resolvers
● resolvers are matched to the schema based on method sets (can resolve a GraphQL schema with a Go
interface or Go struct).
● handles panics in resolvers
● parallel execution of resolvers
● Subscriptions
https://github.com/graph-gophers/graphql-go
13
Setup
graphqlSchema := graphql.MustParseSchema(schema.GetRootSchema(), &resolver.Resolver{})
http.Handle("/graphql", h.AddContext(ctx,
graphqlupload.Handler(
&h.GraphQL{Schema: graphqlSchema},
),
))
Endpoint: https://yourdomain.com/graphql
https://github.com/u007/gographqlstart - sample source code
14
Structure
15
16
How it works
17
http.Handle Schema.Exec Query resolver
Mutation
resolver
Model resolver
Return
Query resolver
Mutation
resolver
Query & Mutation example
● Query - query list / single object
● Mutation - update, delete, create
● Subscription - subscribe to update or event
https://github.com/u007/gographqlstart/blob/master/resolver/user_query.go
https://github.com/u007/gographqlstart/blob/master/resolver/user_mutation.go
18
Demo...
19
Questions?
20
What is DGraph?
21
https://dgraph.io/
What is DGraph?
22
https://dgraph.io/
What is DGraph?
23
https://dgraph.io/
What is DGraph?
24
Dgraph is a distributed, low-latency, high throughput graph database, written in Go. It puts a lot of emphasis on good
design, concurrency and minimizing network calls required to execute a query in a distributed environment.
Why build Dgraph?
We think graph databases are currently second class citizens. They are not considered mature enough to be run as the
sole database, and get run alongside other SQL/NoSQL databases. Also, we’re not happy with the design decisions of
existing graph databases, which are either non-native or non-distributed, don’t manage underlying data or suffer from
performance issues.
Is Dgraph production ready?
We recommend Dgraph to be used in production at companies.
https://dgraph.io/
Why DGraph
Why Graph db.
25
What is Graph database?
26
What is Graph?
A graph is composed of two elements: a node and a relationship.
Each node represents an entity (a person, place, thing, category or other piece of data), and each relationship
represents how two nodes are associated. This general-purpose structure allows you to model all kinds of
scenarios – from a system of roads, to a network of devices, to a population’s medical history or anything else
defined by relationships.
source: https://neo4j.com/why-graph-databases/
What is Graph database?
27
A graph database is an online database management system with Create, Read, Update and Delete (CRUD)
operations working on a graph data model.
source: https://neo4j.com/why-graph-databases/
Why Graph database?
28source: https://neo4j.com/why-graph-databases/
Performance
Example SQL with “Join”s
SELECT 'paper_review'::text AS type, paper_reviews.id, paper_reviews.user_id, concat_ws(' '::text, users.first_name, users.last_name) AS
user_full_name, users.title AS user_title, users.photo AS user_photo, users.organization AS user_organization, users.username,
paper_reviews.paper_id, NULL::character varying AS language_framework, NULL::text AS performance_description, paper_reviews.score_tech,
paper_reviews.score_original,
( SELECT count(comments.id) AS count FROM public.comments WHERE ((comments.source_id = paper_reviews.id) AND (comments.vote = 1))) AS
likes_count,
( SELECT count(comments.id) AS count FROM public.comments WHERE ((comments.source_id = paper_reviews.id) AND (comments.vote = 0))) AS
comments_count FROM ((public.paper_reviews LEFT JOIN public.papers ON ((paper_reviews.paper_id = papers.id))) LEFT JOIN public.users ON
((paper_reviews.user_id = users.id)))
UNION SELECT 'paper_code'::text AS type, paper_codes.id, paper_codes.user_id, concat_ws(' '::text, users.first_name, users.last_name) AS
user_full_name, users.title AS user_title, ...
Why Graph database?
29
Performance
NoSQL
Multiple round trip to database server
GraphDB
Single Query with additional relation mapping
Why Graph database?
30
Flexibility
SQL based:
More joins!, more indexing, more optimisations, more group by OR more sub select, or refactor
NoSQL based:
More round trip for additional collection, more indexing
GraphDB
Add relation, add to graphql query, more indexing (for non relation field)
Why Graph database?
31
Agility
Flexible schema, alike nosql
Add more nodes to distribute queries (dgraph - distributed)
Why Graph database?
32
DGraph Setup
● Zero node: controls the Dgraph cluster, assigns servers to a group and re-balances data between server
groups
● Alpha node: hosts predicates and indexes
● Ratel: UI to run queries, mutations & altering schema (alike pgadmin)
https://docs.dgraph.io/get-started/
https://tour.dgraph.io/intro/1/
https://gist.github.com/u007/f47f9e42ae4f7a94b29c542955d698bc - docker-compose example
33
DGraph: Declaring schema
name: string @index(term) @lang .
age: int @index(int) .
friend: uid @count @reverse .
https://tour.dgraph.io/basic/3/ - data types
https://docs.dgraph.io/query-language/#schema-types
https://docs.dgraph.io/query-language/#indexing
34
DGraph: GO Client
go get -u -v github.com/dgraph-io/dgo
---
conn, err := grpc.Dial("localhost:9080", grpc.WithInsecure())
if err != nil {
log.Fatal(err)
}
defer conn.Close()
dgraphClient := dgo.NewDgraphClient(api.NewDgraphClient(conn))
op := &api.Operation{
Schema: `name: string @index(exact) .
age: int @index(int) .`,
}
err := dgraphClient.Alter(ctx, op) 35
DGraph: Updating/Deleting/Mutate
txn := dgraphClient.NewTxn()
defer txn.Discard(ctx)
type Person struct {
Uid string `json:"uid,omitempty"`
Name string `json:"name,omitempty"`
}
p := Person{
Uid: "_:alice",//optional
Name: "Alice",
}
36
pb, err := json.Marshal(p)
if err != nil {
log.Fatal(err)
}
mu := &api.Mutation{
SetJson: pb,
}
assigned, err := txn.Mutate(ctx, mu)
if err != nil {
log.Fatal(err)
}
DGraph: Committing transaction / discard
txn := dgraphClient.NewTxn()
defer txn.Discard(ctx)
err := txn.Commit(ctx)
if err == y.ErrAborted {
// Retry or handle error
}
37
DGraph: Query Single object
q := `query all($a: string) {
all(func: eq(name, $a)) {
name
}
}`
resp, err := txn.QueryWithVars(ctx, q,
map[string]string{"$a": "Alice"})
fmt.Println(string(resp.Json))
{
user(func: uid(0xc351)) {
First_name
Last_name
Email
roles: with_role {
Uid
Name
}
}
}
38
DGraph: Query list
users(func: eq(_type, "users"), first: 10,
offset:0, orderdesc: created_at)
@filter(has(with_role)) {
uid
email
first_name
company : work_for {
uid
code
name
}
}
}
39
Questions?
40
Me want more...
● https://github.com/graph-gophers/graphql-go
● https://graphql.org/learn/
● https://docs.dgraph.io/get-started/
● DGraph quick start:
https://gist.github.com/u007/5f68d68d9ee5ad30a10b92ed932b1639
41

GraphQL & DGraph with Go

  • 1.
  • 2.
    James tan @ OkestraSystems Sdn Bhd | https://okestra.co/ | james@okestra.co | 0123221812 2 Workflow management simplified Let’s make GO fun! With AI (soon)
  • 3.
    What is GraphQL? GraphQLis a query language for APIs and a runtime for fulfilling those queries with your existing data. 3
  • 4.
    Who uses GraphQL? 4 Andmore @ https://graphql.org/users/
  • 5.
    Trusty REST GET, POST,HEAD, DELETE, OPTIONS, PUT, TRACE, CONNECT GET /pages GET /pages/5 POST /pages PUT /pages/5 DELETE /pages/5 Examples: 5
  • 6.
  • 7.
    Multiple Round Trip 7 ● fetch/pages/1 ● fetch /comments?pageID=1 ● fetch /users/2 query page($id: Int) { page(ID: $id) { title description comments { id message created_by { id name } } } } REST: GraphQL:
  • 8.
    Multiple Round Trip 8 ● fetch/pages/1 ● fetch /comments?pageID=1 ● fetch /users/2 query page($id: Int) { page(ID: $id) { title description comments { id message created_by { id name } } } announcements() { edges { node: { id title message } } } REST: GraphQL:
  • 9.
    Over fetching data 9 ●Frontend: fetch /pages ● Admin: fetch /pages Frontend: Admin: title date description title date description ... ID title Created by Created on Published 1 Title here ... ... Yes 2 comments 5 comments [ { id: 1, title: “title”, description: “...”, created_at: “...”, created_by: { name: “...” }, Comments_count: 2 }, … ] REST Frontend & admin:
  • 10.
    Over fetching data 10 Frontend: Admin: titledate description title date description ... ID title Created by Created on Published 1 Title here ... ... Yes 2 comments 5 comments query page($id: Int) { page(ID: $id) { title description Comment_count … }} GraphQL frontend: query page($id: Int) { page(ID: $id) { Title … }} GraphQL admin:
  • 11.
    Schema Documentation 11 Allow APIDiscovery and exploration REST: schema { query: Query mutation: Mutation } type Query { user(email: String!): User users(first: Int, after: String): UsersConnection! } type Mutation { createUser(email: String!, password: String!): User }
  • 12.
    Implementing GraphQL ● graphql-go:An implementation of GraphQL for Go / Golang. ● graph-gophers/graphql-go: An active implementation of GraphQL in Golang (was https://github.com/graph-gophers/graphql-go). ● GQLGen - Go generate based graphql server library. ● graphql-relay-go: A Go/Golang library to help construct a graphql-go server supporting react-relay. ● machinebox/graphql: An elegant low-level HTTP client for GraphQL. ● samsarahq/thunder: A GraphQL implementation with easy schema building, live queries, and batching 12 https://graphql.org/code/#go
  • 13.
    Graphql-go ● minimal API ●support for context.Context ● support for the OpenTracing standard ● schema type-checking against resolvers ● resolvers are matched to the schema based on method sets (can resolve a GraphQL schema with a Go interface or Go struct). ● handles panics in resolvers ● parallel execution of resolvers ● Subscriptions https://github.com/graph-gophers/graphql-go 13
  • 14.
    Setup graphqlSchema := graphql.MustParseSchema(schema.GetRootSchema(),&resolver.Resolver{}) http.Handle("/graphql", h.AddContext(ctx, graphqlupload.Handler( &h.GraphQL{Schema: graphqlSchema}, ), )) Endpoint: https://yourdomain.com/graphql https://github.com/u007/gographqlstart - sample source code 14
  • 15.
  • 16.
  • 17.
    How it works 17 http.HandleSchema.Exec Query resolver Mutation resolver Model resolver Return Query resolver Mutation resolver
  • 18.
    Query & Mutationexample ● Query - query list / single object ● Mutation - update, delete, create ● Subscription - subscribe to update or event https://github.com/u007/gographqlstart/blob/master/resolver/user_query.go https://github.com/u007/gographqlstart/blob/master/resolver/user_mutation.go 18
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
    What is DGraph? 24 Dgraphis a distributed, low-latency, high throughput graph database, written in Go. It puts a lot of emphasis on good design, concurrency and minimizing network calls required to execute a query in a distributed environment. Why build Dgraph? We think graph databases are currently second class citizens. They are not considered mature enough to be run as the sole database, and get run alongside other SQL/NoSQL databases. Also, we’re not happy with the design decisions of existing graph databases, which are either non-native or non-distributed, don’t manage underlying data or suffer from performance issues. Is Dgraph production ready? We recommend Dgraph to be used in production at companies. https://dgraph.io/
  • 25.
  • 26.
    What is Graphdatabase? 26 What is Graph? A graph is composed of two elements: a node and a relationship. Each node represents an entity (a person, place, thing, category or other piece of data), and each relationship represents how two nodes are associated. This general-purpose structure allows you to model all kinds of scenarios – from a system of roads, to a network of devices, to a population’s medical history or anything else defined by relationships. source: https://neo4j.com/why-graph-databases/
  • 27.
    What is Graphdatabase? 27 A graph database is an online database management system with Create, Read, Update and Delete (CRUD) operations working on a graph data model. source: https://neo4j.com/why-graph-databases/
  • 28.
    Why Graph database? 28source:https://neo4j.com/why-graph-databases/
  • 29.
    Performance Example SQL with“Join”s SELECT 'paper_review'::text AS type, paper_reviews.id, paper_reviews.user_id, concat_ws(' '::text, users.first_name, users.last_name) AS user_full_name, users.title AS user_title, users.photo AS user_photo, users.organization AS user_organization, users.username, paper_reviews.paper_id, NULL::character varying AS language_framework, NULL::text AS performance_description, paper_reviews.score_tech, paper_reviews.score_original, ( SELECT count(comments.id) AS count FROM public.comments WHERE ((comments.source_id = paper_reviews.id) AND (comments.vote = 1))) AS likes_count, ( SELECT count(comments.id) AS count FROM public.comments WHERE ((comments.source_id = paper_reviews.id) AND (comments.vote = 0))) AS comments_count FROM ((public.paper_reviews LEFT JOIN public.papers ON ((paper_reviews.paper_id = papers.id))) LEFT JOIN public.users ON ((paper_reviews.user_id = users.id))) UNION SELECT 'paper_code'::text AS type, paper_codes.id, paper_codes.user_id, concat_ws(' '::text, users.first_name, users.last_name) AS user_full_name, users.title AS user_title, ... Why Graph database? 29
  • 30.
    Performance NoSQL Multiple round tripto database server GraphDB Single Query with additional relation mapping Why Graph database? 30
  • 31.
    Flexibility SQL based: More joins!,more indexing, more optimisations, more group by OR more sub select, or refactor NoSQL based: More round trip for additional collection, more indexing GraphDB Add relation, add to graphql query, more indexing (for non relation field) Why Graph database? 31
  • 32.
    Agility Flexible schema, alikenosql Add more nodes to distribute queries (dgraph - distributed) Why Graph database? 32
  • 33.
    DGraph Setup ● Zeronode: controls the Dgraph cluster, assigns servers to a group and re-balances data between server groups ● Alpha node: hosts predicates and indexes ● Ratel: UI to run queries, mutations & altering schema (alike pgadmin) https://docs.dgraph.io/get-started/ https://tour.dgraph.io/intro/1/ https://gist.github.com/u007/f47f9e42ae4f7a94b29c542955d698bc - docker-compose example 33
  • 34.
    DGraph: Declaring schema name:string @index(term) @lang . age: int @index(int) . friend: uid @count @reverse . https://tour.dgraph.io/basic/3/ - data types https://docs.dgraph.io/query-language/#schema-types https://docs.dgraph.io/query-language/#indexing 34
  • 35.
    DGraph: GO Client goget -u -v github.com/dgraph-io/dgo --- conn, err := grpc.Dial("localhost:9080", grpc.WithInsecure()) if err != nil { log.Fatal(err) } defer conn.Close() dgraphClient := dgo.NewDgraphClient(api.NewDgraphClient(conn)) op := &api.Operation{ Schema: `name: string @index(exact) . age: int @index(int) .`, } err := dgraphClient.Alter(ctx, op) 35
  • 36.
    DGraph: Updating/Deleting/Mutate txn :=dgraphClient.NewTxn() defer txn.Discard(ctx) type Person struct { Uid string `json:"uid,omitempty"` Name string `json:"name,omitempty"` } p := Person{ Uid: "_:alice",//optional Name: "Alice", } 36 pb, err := json.Marshal(p) if err != nil { log.Fatal(err) } mu := &api.Mutation{ SetJson: pb, } assigned, err := txn.Mutate(ctx, mu) if err != nil { log.Fatal(err) }
  • 37.
    DGraph: Committing transaction/ discard txn := dgraphClient.NewTxn() defer txn.Discard(ctx) err := txn.Commit(ctx) if err == y.ErrAborted { // Retry or handle error } 37
  • 38.
    DGraph: Query Singleobject q := `query all($a: string) { all(func: eq(name, $a)) { name } }` resp, err := txn.QueryWithVars(ctx, q, map[string]string{"$a": "Alice"}) fmt.Println(string(resp.Json)) { user(func: uid(0xc351)) { First_name Last_name Email roles: with_role { Uid Name } } } 38
  • 39.
    DGraph: Query list users(func:eq(_type, "users"), first: 10, offset:0, orderdesc: created_at) @filter(has(with_role)) { uid email first_name company : work_for { uid code name } } } 39
  • 40.
  • 41.
    Me want more... ●https://github.com/graph-gophers/graphql-go ● https://graphql.org/learn/ ● https://docs.dgraph.io/get-started/ ● DGraph quick start: https://gist.github.com/u007/5f68d68d9ee5ad30a10b92ed932b1639 41

Editor's Notes

  • #4 Can be called via rest post call