Documentation
¶
Overview ¶
Package dgo is used to interact with a Dgraph server. Queries, mutations, and most other types of admin tasks can be run from the client.
Example (GetSchema) ¶
dg, cancel := getDgraphClient()
defer cancel()
op := &api.Operation{}
op.Schema = `
name: string @index(exact) .
age: int .
married: bool .
loc: geo .
dob: datetime .
`
ctx := context.Background()
err := dg.Alter(ctx, op)
if err != nil {
log.Fatal(err)
}
// Ask for the type of name and age.
resp, err := dg.NewTxn().Query(ctx, `schema(pred: [name, age]) {type}`)
if err != nil {
log.Fatal(err)
}
// resp.Json contains the schema query response.
fmt.Println(string(resp.Json))
Output: {"schema":[{"predicate":"age","type":"int"},{"predicate":"name","type":"string"}]}
Example (SetObject) ¶
/*
* SPDX-FileCopyrightText: © Hypermode Inc. <hello@hypermode.com>
* SPDX-License-Identifier: Apache-2.0
*/
package main
import (
"context"
"encoding/json"
"fmt"
"log"
"time"
"github.com/dgraph-io/dgo/v250/protos/api"
)
type School struct {
Name string `json:"name,omitempty"`
DType []string `json:"dgraph.type,omitempty"`
}
type loc struct {
Type string `json:"type,omitempty"`
Coords []float64 `json:"coordinates,omitempty"`
}
// If omitempty is not set, then edges with empty values (0 for int/float, "" for string,
// false for bool) would be created for values not specified explicitly.
type Person struct {
Uid string `json:"uid,omitempty"`
Name string `json:"name,omitempty"`
Age int `json:"age,omitempty"`
Dob *time.Time `json:"dob,omitempty"`
Married bool `json:"married,omitempty"`
Raw []byte `json:"raw_bytes,omitempty"`
Friends []Person `json:"friend,omitempty"`
Location loc `json:"loc,omitempty"`
School []School `json:"school,omitempty"`
DType []string `json:"dgraph.type,omitempty"`
}
func main() {
dg, cancel := getDgraphClient()
defer cancel()
dob := time.Date(1980, 01, 01, 23, 0, 0, 0, time.UTC)
// While setting an object if a struct has a Uid then its properties
// in the graph are updated else a new node is created.
// In the example below new nodes for Alice, Bob and Charlie and
// school are created (since they don't have a Uid).
p := Person{
Uid: "_:alice",
Name: "Alice",
Age: 26,
Married: true,
DType: []string{"Person"},
Location: loc{
Type: "Point",
Coords: []float64{1.1, 2},
},
Dob: &dob,
Raw: []byte("raw_bytes"),
Friends: []Person{{
Name: "Bob",
Age: 24,
DType: []string{"Person"},
}, {
Name: "Charlie",
Age: 29,
DType: []string{"Person"},
}},
School: []School{{
Name: "Crown Public School",
DType: []string{"Institution"},
}},
}
op := &api.Operation{}
op.Schema = `
name: string @index(exact) .
age: int .
married: bool .
loc: geo .
dob: datetime .
Friend: [uid] .
type: string .
coords: float .
type Person {
name: string
age: int
married: bool
Friend: [Person]
loc: Loc
}
type Institution {
name: string
}
type Loc {
type: string
coords: float
}
`
ctx := context.Background()
if err := dg.Alter(ctx, op); err != nil {
log.Fatal(err)
}
mu := &api.Mutation{
CommitNow: true,
}
pb, err := json.Marshal(p)
if err != nil {
log.Fatal(err)
}
mu.SetJson = pb
response, err := dg.NewTxn().Mutate(ctx, mu)
if err != nil {
log.Fatal(err)
}
// Assigned uids for nodes which were created would be returned in the response.Uids map.
variables := map[string]string{"$id1": response.Uids["alice"]}
q := `query Me($id1: string){
me(func: uid($id1)) {
name
dob
age
loc
raw_bytes
married
dgraph.type
friend @filter(eq(name, "Bob")){
name
age
dgraph.type
}
school {
name
dgraph.type
}
}
}`
resp, err := dg.NewTxn().QueryWithVars(ctx, q, variables)
if err != nil {
log.Fatal(err)
}
type Root struct {
Me []Person `json:"me"`
}
var r Root
err = json.Unmarshal(resp.Json, &r)
if err != nil {
log.Fatal(err)
}
out, _ := json.MarshalIndent(r, "", "\t")
fmt.Printf("%s\n", out)
}
Output: { "me": [ { "name": "Alice", "age": 26, "dob": "1980-01-01T23:00:00Z", "married": true, "raw_bytes": "cmF3X2J5dGVz", "friend": [ { "name": "Bob", "age": 24, "loc": {}, "dgraph.type": [ "Person" ] } ], "loc": { "type": "Point", "coordinates": [ 1.1, 2 ] }, "school": [ { "name": "Crown Public School", "dgraph.type": [ "Institution" ] } ], "dgraph.type": [ "Person" ] } ] }
Index ¶
- Variables
- func DeleteEdges(mu *api.Mutation, uid string, predicates ...string)
- func DialCloud(endpoint, key string) (*grpc.ClientConn, error)deprecated
- type ClientOption
- func WithACLCreds(username, password string) ClientOption
- func WithBearerToken(token string) ClientOption
- func WithDgraphAPIKey(apiKey string) ClientOption
- func WithGrpcOption(opt grpc.DialOption) ClientOption
- func WithNamespace(nsID uint64) ClientOption
- func WithSkipTLSVerify() ClientOption
- func WithSystemCertPool() ClientOption
- type Dgraph
- func (d *Dgraph) AllocateNamespaces(ctx context.Context, howMany uint64) (uint64, uint64, error)
- func (d *Dgraph) AllocateTimestamps(ctx context.Context, howMany uint64) (uint64, uint64, error)
- func (d *Dgraph) AllocateUIDs(ctx context.Context, howMany uint64) (uint64, uint64, error)
- func (d *Dgraph) Alter(ctx context.Context, op *api.Operation) error
- func (d *Dgraph) Close()
- func (d *Dgraph) CreateNamespace(ctx context.Context) (uint64, error)
- func (d *Dgraph) DropAll(ctx context.Context) error
- func (d *Dgraph) DropData(ctx context.Context) error
- func (d *Dgraph) DropNamespace(ctx context.Context, nsID uint64) error
- func (d *Dgraph) DropPredicate(ctx context.Context, predicate string) error
- func (d *Dgraph) DropType(ctx context.Context, typeName string) error
- func (d *Dgraph) GetAPIClients() []api.DgraphClient
- func (d *Dgraph) GetJwt() api.Jwt
- func (d *Dgraph) ListNamespaces(ctx context.Context) (map[uint64]*api.Namespace, error)
- func (d *Dgraph) Login(ctx context.Context, userid string, password string) error
- func (d *Dgraph) LoginIntoNamespace(ctx context.Context, userid string, password string, namespace uint64) error
- func (d *Dgraph) NewReadOnlyTxn() *Txn
- func (d *Dgraph) NewTxn() *Txn
- func (d *Dgraph) Relogin(ctx context.Context) error
- func (d *Dgraph) RunDQL(ctx context.Context, q string, opts ...TxnOption) (*api.Response, error)
- func (d *Dgraph) RunDQLWithVars(ctx context.Context, q string, vars map[string]string, opts ...TxnOption) (*api.Response, error)
- func (d *Dgraph) SetSchema(ctx context.Context, schema string) error
- type Txn
- func (txn *Txn) BestEffort() *Txn
- func (txn *Txn) Commit(ctx context.Context) error
- func (txn *Txn) Discard(ctx context.Context) error
- func (txn *Txn) Do(ctx context.Context, req *api.Request) (*api.Response, error)
- func (txn *Txn) Mutate(ctx context.Context, mu *api.Mutation) (*api.Response, error)
- func (txn *Txn) Query(ctx context.Context, q string) (*api.Response, error)
- func (txn *Txn) QueryRDF(ctx context.Context, q string) (*api.Response, error)
- func (txn *Txn) QueryRDFWithVars(ctx context.Context, q string, vars map[string]string) (*api.Response, error)
- func (txn *Txn) QueryWithVars(ctx context.Context, q string, vars map[string]string) (*api.Response, error)
- type TxnOption
Examples ¶
- Package (GetSchema)
- Package (SetObject)
- DeleteEdges
- Dgraph.Alter (DropAll)
- Txn.Discard
- Txn.Mutate
- Txn.Mutate (Bytes)
- Txn.Mutate (DeleteNode)
- Txn.Mutate (DeletePredicate)
- Txn.Mutate (Facets)
- Txn.Mutate (List)
- Txn.Mutate (Upsert)
- Txn.Mutate (UpsertJSON)
- Txn.Query (Besteffort)
- Txn.Query (Unmarshal)
- Txn.Query (Variables)
Constants ¶
This section is empty.
Variables ¶
var ( // ErrFinished is returned when an operation is performed on // already committed or discarded transaction ErrFinished = errors.New("Transaction has already been committed or discarded") // ErrReadOnly is returned when a write/update is performed on a readonly transaction ErrReadOnly = errors.New("Readonly transaction cannot run mutations or be committed") // ErrAborted is returned when an operation is performed on an aborted transaction. ErrAborted = errors.New("Transaction has been aborted. Please retry") )
Functions ¶
func DeleteEdges ¶
DeleteEdges sets the edges corresponding to predicates on the node with the given uid for deletion. This helper function doesn't run the mutation on the server. Txn needs to be committed in order to execute the mutation.
Example ¶
dg, cancel := getDgraphClient()
defer cancel()
op := &api.Operation{}
op.Schema = `
age: int .
married: bool .
name: string @lang .
location: string .
Friends: [uid] .
type Person {
name
age
married
Friends
}
type Institution {
name
}
`
ctx := context.Background()
err := dg.Alter(ctx, op)
if err != nil {
log.Fatal(err)
}
type School struct {
Uid string `json:"uid"`
Name string `json:"name@en,omitempty"`
DType []string `json:"dgraph.type,omitempty"`
}
type Person struct {
Uid string `json:"uid,omitempty"`
Name string `json:"name,omitempty"`
Age int `json:"age,omitempty"`
Married bool `json:"married,omitempty"`
Friends []Person `json:"friends,omitempty"`
Location string `json:"location,omitempty"`
Schools []*School `json:"schools,omitempty"`
DType []string `json:"dgraph.type,omitempty"`
}
// Lets add some data first.
p := Person{
Uid: "_:alice",
Name: "Alice",
Age: 26,
Married: true,
DType: []string{"Person"},
Location: "Riley Street",
Friends: []Person{{
Name: "Bob",
Age: 24,
DType: []string{"Person"},
}, {
Name: "Charlie",
Age: 29,
DType: []string{"Person"},
}},
Schools: []*School{{
Name: "Crown Public School",
DType: []string{"Institution"},
}},
}
mu := &api.Mutation{}
pb, err := json.Marshal(p)
if err != nil {
log.Fatal(err)
}
mu.SetJson = pb
mu.CommitNow = true
response, err := dg.NewTxn().Mutate(ctx, mu)
if err != nil {
log.Fatal(err)
}
alice := response.Uids["alice"]
variables := make(map[string]string)
variables["$alice"] = alice
const q = `
query Me($alice: string){
me(func: uid($alice)) {
name
age
location
married
dgraph.type
friends {
name
age
dgraph.type
}
schools {
name@en
dgraph.type
}
}
}
`
resp, err := dg.NewTxn().QueryWithVars(ctx, q, variables)
if err != nil {
log.Fatal(err)
}
// Now lets delete the friend and location edge from Alice
mu = &api.Mutation{}
dgo.DeleteEdges(mu, alice, "friends", "location")
mu.CommitNow = true
_, err = dg.NewTxn().Mutate(ctx, mu)
if err != nil {
log.Fatal(err)
}
resp, err = dg.NewTxn().QueryWithVars(ctx, q, variables)
if err != nil {
log.Fatal(err)
}
type Root struct {
Me []Person `json:"me"`
}
var r Root
if err := json.Unmarshal(resp.Json, &r); err != nil {
log.Fatal(err)
}
out, _ := json.MarshalIndent(r.Me, "", "\t")
fmt.Printf("%s\n", out)
Output: [ { "name": "Alice", "age": 26, "married": true, "schools": [ { "uid": "", "name@en": "Crown Public School", "dgraph.type": [ "Institution" ] } ], "dgraph.type": [ "Person" ] } ]
func DialCloud
deprecated
func DialCloud(endpoint, key string) (*grpc.ClientConn, error)
DialCloud creates a new TLS connection to a Dgraph Cloud backend
It requires the backend endpoint as well as the api token
Usage:
conn, err := dgo.DialCloud("CLOUD_ENDPOINT","API_TOKEN")
if err != nil {
log.Fatal(err)
}
defer conn.Close()
dgraphClient := dgo.NewDgraphClient(api.NewDgraphClient(conn))
Deprecated: Use dgo.NewClient or dgo.Open instead.
Types ¶
type ClientOption ¶
type ClientOption func(*clientOptions) error
ClientOption is a function that modifies the client options.
func WithACLCreds ¶
func WithACLCreds(username, password string) ClientOption
WithACLCreds will use the provided username and password for ACL authentication. If namespace is not provided, it logs into the galaxy namespace.
func WithBearerToken ¶
func WithBearerToken(token string) ClientOption
WithBearerToken uses the provided token and presents it as a Bearer Token in the HTTP Authorization header for authentication against a Dgraph Cluster. This can be used to connect to Hypermode Cloud.
func WithDgraphAPIKey ¶
func WithDgraphAPIKey(apiKey string) ClientOption
WithDgraphAPIKey will use the provided API key for authentication for Dgraph Cloud.
func WithGrpcOption ¶
func WithGrpcOption(opt grpc.DialOption) ClientOption
WithGrpcOption will add a grpc.DialOption to the client. This is useful for setting custom grpc options.
func WithNamespace ¶
func WithNamespace(nsID uint64) ClientOption
WithNamespace logs into the given namespace.
func WithSkipTLSVerify ¶
func WithSkipTLSVerify() ClientOption
func WithSystemCertPool ¶
func WithSystemCertPool() ClientOption
WithSystemCertPool will use the system cert pool and setup a TLS connection with Dgraph cluster.
type Dgraph ¶
type Dgraph struct {
// contains filtered or unexported fields
}
Dgraph is a transaction-aware client to a Dgraph cluster.
func NewClient ¶
func NewClient(endpoint string, opts ...ClientOption) (*Dgraph, error)
NewClient creates a new Dgraph client for a single endpoint. If ACL connection options are present, an login attempt is made using the supplied credentials.
func NewDgraphClient
deprecated
func NewDgraphClient(clients ...api.DgraphClient) *Dgraph
NewDgraphClient creates a new Dgraph (client) for interacting with Alphas. The client is backed by multiple connections to the same or different servers in a cluster.
A single Dgraph (client) is thread safe for sharing with multiple goroutines.
Deprecated: Use dgo.NewClient or dgo.Open instead.
func NewRoundRobinClient ¶
func NewRoundRobinClient(endpoints []string, opts ...ClientOption) (*Dgraph, error)
NewRoundRobinClient creates a new Dgraph client for a list of endpoints. It will round robin among the provided endpoints. If ACL connection options are present, an login attempt is made using the supplied credentials.
func Open ¶
Open creates a new Dgraph client by parsing a connection string of the form: dgraph://<optional-login>:<optional-password>@<host>:<port>?<optional-params> For example `dgraph://localhost:9080?sslmode=require`
Parameters: - apikey: a Dgraph Cloud API key for authentication - bearertoken: a token for bearer authentication - sslmode: SSL connection mode (options: disable, require, verify-ca)
- disable: No TLS (default)
- require: Use TLS but skip certificate verification
- verify-ca: Use TLS and verify the certificate against system CA
If credentials are provided, Open connects to the gRPC endpoint and authenticates the user. An error can be returned if the Dgraph cluster is not yet ready to accept requests--the text of the error in this case will contain the string "Please retry".
func (*Dgraph) AllocateNamespaces ¶
AllocateNamespaces allocates a given number of namespaces in the Graph and returns a start and end namespaces, end excluded. The namespaces in the range [start, end) can then be used by the client. Dgraph ensures that these namespaces are NOT allocated anywhere else throughout the operation of this cluster. This is useful in bulk loader or live loader or similar applications.
func (*Dgraph) AllocateTimestamps ¶
AllocateTimestamps gets a sequence of timestamps allocated from Dgraph. These timestamps can be used in bulk loader and similar applications.
func (*Dgraph) AllocateUIDs ¶
AllocateUIDs allocates a given number of Node UIDs in the Graph and returns a start and end UIDs, end excluded. The UIDs in the range [start, end) can then be used by the client in the mutations going forward. Note that, each node in a Graph is assigned a UID in Dgraph. Dgraph ensures that these UIDs are not allocated anywhere else throughout the operation of this cluster. This is useful in bulk loader or live loader or similar applications.
func (*Dgraph) Alter ¶
Alter can be used to do the following by setting various fields of api.Operation:
- Modify the schema.
- Drop a predicate.
- Drop the database.
Use DropAll, DropData, DropPredicate, DropType, SetSchema instead for better readability.
Example (DropAll) ¶
dg, cancel := getDgraphClient()
defer cancel()
op := api.Operation{DropAll: true}
ctx := context.Background()
if err := dg.Alter(ctx, &op); err != nil {
log.Fatal(err)
}
func (*Dgraph) Close ¶
func (d *Dgraph) Close()
Close shutdown down all the connections to the Dgraph Cluster.
func (*Dgraph) CreateNamespace ¶
CreateNamespace creates a new namespace with the given name and password for groot user.
func (*Dgraph) DropNamespace ¶
DropNamespace deletes the namespace with the given name.
func (*Dgraph) DropPredicate ¶
func (*Dgraph) GetAPIClients ¶
func (d *Dgraph) GetAPIClients() []api.DgraphClient
GetAPIClients returns the api.DgraphClient that is useful for advanced cases when grpc API that are not exposed in dgo needs to be used.
func (*Dgraph) ListNamespaces ¶
ListNamespaces returns a map of namespace names to their details.
func (*Dgraph) Login ¶
Login logs in the current client using the provided credentials into default namespace (0). Valid for the duration the client is alive.
func (*Dgraph) LoginIntoNamespace ¶
func (d *Dgraph) LoginIntoNamespace(ctx context.Context, userid string, password string, namespace uint64) error
LoginIntoNamespace logs in the current client using the provided credentials. Valid for the duration the client is alive.
func (*Dgraph) NewReadOnlyTxn ¶
NewReadOnlyTxn sets the txn to readonly transaction.
func (*Dgraph) Relogin ¶
Relogin relogin the current client using the refresh token. This can be used when the access-token gets expired.
func (*Dgraph) RunDQL ¶
RunDQL runs a DQL query in the given namespace. A DQL query could be a mutation or a query or an upsert which is a combination of mutations and queries.
type Txn ¶
type Txn struct {
// contains filtered or unexported fields
}
Txn is a single atomic transaction. A transaction lifecycle is as follows:
- Created using NewTxn.
- Various Query and Mutate calls made.
- Commit or Discard used. If any mutations have been made, It's important that at least one of these methods is called to clean up resources. Discard is a no-op if Commit has already been called, so it's safe to defer a call to Discard immediately after NewTxn.
func (*Txn) BestEffort ¶
BestEffort enables best effort in read-only queries. This will ask the Dgraph Alpha to try to get timestamps from memory in a best effort to reduce the number of outbound requests to Zero. This may yield improved latencies in read-bound datasets.
This method will panic if the transaction is not read-only. Returns the transaction itself.
func (*Txn) Commit ¶
Commit commits any mutations that have been made in the transaction. Once Commit has been called, the lifespan of the transaction is complete.
Errors could be returned for various reasons. Notably, ErrAborted could be returned if transactions that modify the same data are being run concurrently. It's up to the user to decide if they wish to retry. In this case, the user should create a new transaction.
func (*Txn) Discard ¶
Discard cleans up the resources associated with an uncommitted transaction that contains mutations. It is a no-op on transactions that have already been committed or don't contain mutations. Therefore, it is safe (and recommended) to call as a deferred function immediately after a new transaction is created.
In some cases, the transaction can't be discarded, e.g. the grpc connection is unavailable. In these cases, the server will eventually do the transaction clean up itself without any intervention from the client.
Example ¶
dg, cancel := getDgraphClient()
defer cancel()
ctx, toCancel := context.WithTimeout(context.Background(), 30*time.Second)
defer toCancel()
err := dg.Alter(ctx, &api.Operation{
DropAll: true,
})
if err != nil {
log.Fatal("The drop all operation should have succeeded")
}
err = dg.Alter(ctx, &api.Operation{
Schema: `name: string @index(exact) .`,
})
if err != nil {
log.Fatal("The alter should have succeeded")
}
txn := dg.NewTxn()
_, err = txn.Mutate(ctx, &api.Mutation{
SetNquads: []byte(`_:a <name> "Alice" .`),
})
if err != nil {
log.Fatal("The mutation should have succeeded")
}
if err := txn.Discard(ctx); err != nil {
log.Fatal(err)
}
// now query the cluster and make sure that the data has made no effect
queryTxn := dg.NewReadOnlyTxn()
query := `
{
q (func: eq(name, "Alice")) {
name
dgraph.type
}
}
`
resp, err := queryTxn.Query(ctx, query)
if err != nil {
log.Fatal("The query should have succeeded")
}
fmt.Print(string(resp.Json))
Output: {"q":[]}
func (*Txn) Mutate ¶
Mutate allows data stored on Dgraph instances to be modified. The fields in api.Mutation come in pairs, set and delete. Mutations can either be encoded as JSON or as RDFs.
If CommitNow is set, then this call will result in the transaction being committed. In this case, an explicit call to Commit doesn't need to be made subsequently.
If the mutation fails, then the transaction is discarded and all future operations on it will fail.
Example ¶
type School struct {
Name string `json:"name,omitempty"`
DType []string `json:"dgraph.type,omitempty"`
}
type loc struct {
Type string `json:"type,omitempty"`
Coords []float64 `json:"coordinates,omitempty"`
}
// If omitempty is not set, then edges with empty values (0 for int/float, "" for string,
// false for bool) would be created for values not specified explicitly.
type Person struct {
Uid string `json:"uid,omitempty"`
Name string `json:"name,omitempty"`
Age int `json:"age,omitempty"`
Married bool `json:"married,omitempty"`
Raw []byte `json:"raw_bytes,omitempty"`
Friends []Person `json:"friends,omitempty"`
Location loc `json:"loc,omitempty"`
School []School `json:"school,omitempty"`
DType []string `json:"dgraph.type,omitempty"`
}
dg, cancel := getDgraphClient()
defer cancel()
// While setting an object if a struct has a Uid then its properties in the
// graph are updated else a new node is created.
// In the example below new nodes for Alice, Bob and Charlie and school
// are created (since they don't have a Uid).
p := Person{
Uid: "_:alice",
Name: "Alice",
Age: 26,
Married: true,
DType: []string{"Person"},
Location: loc{
Type: "Point",
Coords: []float64{1.1, 2},
},
Raw: []byte("raw_bytes"),
Friends: []Person{{
Name: "Bob",
Age: 24,
DType: []string{"Person"},
}, {
Name: "Charlie",
Age: 29,
DType: []string{"Person"},
}},
School: []School{{
Name: "Crown Public School",
DType: []string{"Institution"},
}},
}
op := &api.Operation{}
op.Schema = `
name: string @index(exact) .
age: int .
married: bool .
Friends: [uid] .
loc: geo .
type: string .
coords: float .
type Person {
name
age
married
Friends
loc
}
type Institution {
name
}
`
ctx := context.Background()
if err := dg.Alter(ctx, op); err != nil {
log.Fatal(err)
}
mu := &api.Mutation{
CommitNow: true,
}
pb, err := json.Marshal(p)
if err != nil {
log.Fatal(err)
}
mu.SetJson = pb
response, err := dg.NewTxn().Mutate(ctx, mu)
if err != nil {
log.Fatal(err)
}
// Assigned uids for nodes which were created would be returned in the response.Uids map.
puid := response.Uids["alice"]
const q = `
query Me($id: string){
me(func: uid($id)) {
name
age
loc
raw_bytes
married
dgraph.type
friends @filter(eq(name, "Bob")) {
name
age
dgraph.type
}
school {
name
dgraph.type
}
}
}
`
variables := make(map[string]string)
variables["$id"] = puid
resp, err := dg.NewTxn().QueryWithVars(ctx, q, variables)
if err != nil {
log.Fatal(err)
}
type Root struct {
Me []Person `json:"me"`
}
var r Root
err = json.Unmarshal(resp.Json, &r)
if err != nil {
log.Fatal(err)
}
out, _ := json.MarshalIndent(r, "", "\t")
fmt.Printf("%s\n", out)
Output: { "me": [ { "name": "Alice", "age": 26, "married": true, "raw_bytes": "cmF3X2J5dGVz", "friends": [ { "name": "Bob", "age": 24, "loc": {}, "dgraph.type": [ "Person" ] } ], "loc": { "type": "Point", "coordinates": [ 1.1, 2 ] }, "school": [ { "name": "Crown Public School", "dgraph.type": [ "Institution" ] } ], "dgraph.type": [ "Person" ] } ] }
Example (Bytes) ¶
dg, cancel := getDgraphClient()
defer cancel()
type Person struct {
Uid string `json:"uid,omitempty"`
Name string `json:"name,omitempty"`
Bytes []byte `json:"bytes,omitempty"`
DType []string `json:"dgraph.type,omitempty"`
}
op := &api.Operation{}
op.Schema = `
name: string @index(exact) .
bytes: string .
type Person {
name
bytes
}
`
ctx := context.Background()
err := dg.Alter(ctx, op)
if err != nil {
log.Fatal(err)
}
p := Person{
Name: "Alice-new",
DType: []string{"Person"},
Bytes: []byte("raw_bytes"),
}
mu := &api.Mutation{
CommitNow: true,
}
pb, err := json.Marshal(p)
if err != nil {
log.Fatal(err)
}
mu.SetJson = pb
_, err = dg.NewTxn().Mutate(ctx, mu)
if err != nil {
log.Fatal(err)
}
q := `
{
q(func: eq(name, "Alice-new")) {
name
bytes
dgraph.type
}
}
`
resp, err := dg.NewTxn().Query(ctx, q)
if err != nil {
log.Fatal(err)
}
type Root struct {
Me []Person `json:"q"`
}
var r Root
err = json.Unmarshal(resp.Json, &r)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Me: %+v\n", r.Me)
Output: Me: [{Uid: Name:Alice-new Bytes:[114 97 119 95 98 121 116 101 115] DType:[Person]}]
Example (DeleteNode) ¶
dg, cancel := getDgraphClient()
defer cancel()
// In this test we check S * * deletion.
type Person struct {
Uid string `json:"uid,omitempty"`
Name string `json:"name,omitempty"`
Age int `json:"age,omitempty"`
Married bool `json:"married,omitempty"`
Friends []*Person `json:"friends,omitempty"`
DType []string `json:"dgraph.type,omitempty"`
}
p := Person{
Uid: "_:alice",
Name: "Alice",
Age: 26,
Married: true,
DType: []string{"Person"},
Friends: []*Person{
{
Uid: "_:bob",
Name: "Bob",
Age: 24,
DType: []string{"Person"},
},
{
Uid: "_:charlie",
Name: "Charlie",
Age: 29,
DType: []string{"Person"},
},
},
}
op := &api.Operation{}
op.Schema = `
age: int .
married: bool .
friends: [uid] .
type Person {
name: string
age: int
married: bool
friends: [Person]
}
`
ctx := context.Background()
err := dg.Alter(ctx, op)
if err != nil {
log.Fatal(err)
}
mu := &api.Mutation{
CommitNow: true,
}
pb, err := json.Marshal(p)
if err != nil {
log.Fatal(err)
}
mu.SetJson = pb
response, err := dg.NewTxn().Mutate(ctx, mu)
if err != nil {
log.Fatal(err)
}
alice := response.Uids["alice"]
bob := response.Uids["bob"]
charlie := response.Uids["charlie"]
variables := make(map[string]string)
variables["$alice"] = alice
variables["$bob"] = bob
variables["$charlie"] = charlie
const q = `
query Me($alice: string, $bob: string, $charlie: string){
me(func: uid($alice)) {
name
age
married
dgraph.type
friends {
uid
name
age
dgraph.type
}
}
me2(func: uid($bob)) {
name
age
dgraph.type
}
me3(func: uid($charlie)) {
name
age
dgraph.type
}
}
`
resp, err := dg.NewTxn().QueryWithVars(ctx, q, variables)
if err != nil {
log.Fatal(err)
}
type Root struct {
Me []Person `json:"me"`
Me2 []Person `json:"me2"`
Me3 []Person `json:"me3"`
}
var r Root
if err := json.Unmarshal(resp.Json, &r); err != nil {
log.Fatal(err)
}
// Now lets try to delete Alice. This won't delete Bob and Charlie
// but just remove the connection between Alice and them.
// The JSON for deleting a node should be of the form {"uid": "0x123"}.
// If you wanted to delete multiple nodes you could supply an array of objects
// like [{"uid": "0x321"}, {"uid": "0x123"}] to DeleteJson.
d := map[string]string{"uid": alice}
pb, err = json.Marshal(d)
if err != nil {
log.Fatal(err)
}
mu = &api.Mutation{
CommitNow: true,
DeleteJson: pb,
}
_, err = dg.NewTxn().Mutate(ctx, mu)
if err != nil {
log.Fatal(err)
}
resp, err = dg.NewTxn().QueryWithVars(ctx, q, variables)
if err != nil {
log.Fatal(err)
}
err = json.Unmarshal(resp.Json, &r)
if err != nil {
log.Fatal(err)
}
out, _ := json.MarshalIndent(r, "", "\t")
fmt.Printf("%s\n", out)
Output: { "me": [], "me2": [ { "name": "Bob", "age": 24, "dgraph.type": [ "Person" ] } ], "me3": [ { "name": "Charlie", "age": 29, "dgraph.type": [ "Person" ] } ] }
Example (DeletePredicate) ¶
dg, cancel := getDgraphClient()
defer cancel()
type Person struct {
Uid string `json:"uid,omitempty"`
Name string `json:"name,omitempty"`
Age int `json:"age,omitempty"`
Married bool `json:"married,omitempty"`
Friends []Person `json:"friends,omitempty"`
DType []string `json:"dgraph.type,omitempty"`
}
p := Person{
Uid: "_:alice",
Name: "Alice",
Age: 26,
Married: true,
DType: []string{"Person"},
Friends: []Person{
{
Name: "Bob",
Age: 24,
DType: []string{"Person"},
},
{
Name: "Charlie",
Age: 29,
DType: []string{"Person"},
},
},
}
op := &api.Operation{}
op.Schema = `
name: string .
age: int .
married: bool .
friends: [uid] .
type Person {
name: string
age: int
married: bool
friends: [Person]
}
`
ctx := context.Background()
err := dg.Alter(ctx, op)
if err != nil {
log.Fatal(err)
}
mu := &api.Mutation{
CommitNow: true,
}
pb, err := json.Marshal(p)
if err != nil {
log.Fatal(err)
}
mu.SetJson = pb
response, err := dg.NewTxn().Mutate(ctx, mu)
if err != nil {
log.Fatal(err)
}
alice := response.Uids["alice"]
variables := make(map[string]string)
variables["$id"] = alice
const q = `
query Me($id: string){
me(func: uid($id)) {
name
age
married
dgraph.type
friends {
uid
name
age
dgraph.type
}
}
}
`
resp, err := dg.NewTxn().QueryWithVars(ctx, q, variables)
if err != nil {
log.Fatal(err)
}
type Root struct {
Me []Person `json:"me"`
}
var r Root
err = json.Unmarshal(resp.Json, &r)
if err != nil {
log.Fatal(err)
}
op = &api.Operation{DropAttr: "friends"}
err = dg.Alter(ctx, op)
if err != nil {
log.Fatal(err)
}
op = &api.Operation{DropAttr: "married"}
err = dg.Alter(ctx, op)
if err != nil {
log.Fatal(err)
}
// Also lets run the query again to verify that predicate data was deleted.
resp, err = dg.NewTxn().QueryWithVars(ctx, q, variables)
if err != nil {
log.Fatal(err)
}
r = Root{}
err = json.Unmarshal(resp.Json, &r)
if err != nil {
log.Fatal(err)
}
// Alice should have no friends and only two attributes now.
fmt.Printf("%+v\n", r)
Output: {Me:[{Uid: Name:Alice Age:26 Married:false Friends:[] DType:[Person]}]}
Example (Facets) ¶
dg, cancel := getDgraphClient()
defer cancel()
// Doing a dropAll isn't required by the user. We do it here so that
// we can verify that the example runs as expected.
op := api.Operation{DropAll: true}
ctx := context.Background()
if err := dg.Alter(ctx, &op); err != nil {
log.Fatal(err)
}
op = api.Operation{}
op.Schema = `
name: string @index(exact) .
age: int .
married: bool .
NameOrigin: string .
Since: string .
Family: string .
Age: bool .
Close: bool .
Friends: [uid] .
type Person {
name
age
married
NameOrigin
Since
Family
Age
Close
Friends
}
type Institution {
name
Since
}
`
err := dg.Alter(ctx, &op)
if err != nil {
log.Fatal(err)
}
// This example shows example for SetObject using facets.
type School struct {
Name string `json:"name,omitempty"`
Since time.Time `json:"school|since,omitempty"`
DType []string `json:"dgraph.type,omitempty"`
}
type Person struct {
Uid string `json:"uid,omitempty"`
Name string `json:"name,omitempty"`
NameOrigin string `json:"name|origin,omitempty"`
Friends []Person `json:"friends,omitempty"`
// These are facets on the friend edge.
Since *time.Time `json:"friends|since,omitempty"`
Family string `json:"friends|family,omitempty"`
Age float64 `json:"friends|age,omitempty"`
Close bool `json:"friends|close,omitempty"`
School []School `json:"school,omitempty"`
DType []string `json:"dgraph.type,omitempty"`
}
ti := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
p := Person{
Uid: "_:alice",
Name: "Alice",
NameOrigin: "Indonesia",
DType: []string{"Person"},
Friends: []Person{
{
Name: "Bob",
Since: &ti,
Family: "yes",
Age: 13,
Close: true,
DType: []string{"Person"},
},
{
Name: "Charlie",
Family: "maybe",
Age: 16,
DType: []string{"Person"},
},
},
School: []School{{
Name: "Wellington School",
Since: ti,
DType: []string{"Institution"},
}},
}
mu := &api.Mutation{}
pb, err := json.Marshal(p)
if err != nil {
log.Fatal(err)
}
mu.SetJson = pb
mu.CommitNow = true
response, err := dg.NewTxn().Mutate(ctx, mu)
if err != nil {
log.Fatal(err)
}
auid := response.Uids["alice"]
variables := make(map[string]string)
variables["$id"] = auid
const q = `
query Me($id: string){
me(func: uid($id)) {
name @facets
dgraph.type
friends @filter(eq(name, "Bob")) @facets {
name
dgraph.type
}
school @facets {
name
dgraph.type
}
}
}
`
resp, err := dg.NewTxn().QueryWithVars(ctx, q, variables)
if err != nil {
log.Fatal(err)
}
type Root struct {
Me []Person `json:"me"`
}
var r Root
err = json.Unmarshal(resp.Json, &r)
if err != nil {
log.Fatal(err)
}
out, _ := json.MarshalIndent(r.Me, "", "\t")
fmt.Printf("%s\n", out)
Output: [ { "name": "Alice", "name|origin": "Indonesia", "friends": [ { "name": "Bob", "friends|since": "2009-11-10T23:00:00Z", "friends|family": "yes", "friends|age": 13, "friends|close": true, "dgraph.type": [ "Person" ] } ], "school": [ { "name": "Wellington School", "school|since": "2009-11-10T23:00:00Z", "dgraph.type": [ "Institution" ] } ], "dgraph.type": [ "Person" ] } ]
Example (List) ¶
dg, cancel := getDgraphClient()
defer cancel() // This example shows example for SetObject for predicates with list type.
type Person struct {
Uid string `json:"uid"`
Address []string `json:"address"`
PhoneNumber []int64 `json:"phone_number"`
DType []string `json:"dgraph.type,omitempty"`
}
p := Person{
Uid: "_:person",
Address: []string{"Redfern", "Riley Street"},
PhoneNumber: []int64{9876, 123},
DType: []string{"Person"},
}
op := &api.Operation{}
op.Schema = `
address: [string] .
phone_number: [int] .
type Person {
Address
phone_number
}
`
ctx := context.Background()
err := dg.Alter(ctx, op)
if err != nil {
log.Fatal(err)
}
mu := &api.Mutation{}
pb, err := json.Marshal(p)
if err != nil {
log.Fatal(err)
}
mu.SetJson = pb
mu.CommitNow = true
response, err := dg.NewTxn().Mutate(ctx, mu)
if err != nil {
log.Fatal(err)
}
variables := map[string]string{"$id": response.Uids["person"]}
const q = `
query Me($id: string){
me(func: uid($id)) {
address
phone_number
dgraph.type
}
}
`
resp, err := dg.NewTxn().QueryWithVars(ctx, q, variables)
if err != nil {
log.Fatal(err)
}
type Root struct {
Me []Person `json:"me"`
}
var r Root
err = json.Unmarshal(resp.Json, &r)
if err != nil {
log.Fatal(err)
}
// List items aren't guaranteed to be in the same order.
fmt.Println(string(resp.Json))
// {"me":[{"address":["Riley Street","Redfern"],"phone_number":[9876,123]}]}
Example (Upsert) ¶
dg, cancel := getDgraphClient()
defer cancel()
ctx, toCancel := context.WithTimeout(context.Background(), 30*time.Second)
defer toCancel()
// Warn: Cleaning up the database
if err := dg.Alter(ctx, &api.Operation{DropAll: true}); err != nil {
log.Fatal("The drop all operation should have succeeded")
}
op := &api.Operation{}
op.Schema = `
name: string .
email: string @index(exact) .`
if err := dg.Alter(ctx, op); err != nil {
log.Fatal(err)
}
m1 := `
_:n1 <name> "user" .
_:n1 <email> "user@dgraphO.io" .
`
mu := &api.Mutation{
SetNquads: []byte(m1),
CommitNow: true,
}
if _, err := dg.NewTxn().Mutate(ctx, mu); err != nil {
log.Fatal(err)
}
req := &api.Request{CommitNow: true}
req.Query = `
query {
me(func: eq(email, "user@dgraphO.io")) {
v as uid
}
}
`
m2 := `uid(v) <email> "user@dgraph.io" .`
mu.SetNquads = []byte(m2)
req.Mutations = []*api.Mutation{mu}
// Update email only if matching uid found.
if _, err := dg.NewTxn().Do(ctx, req); err != nil {
log.Fatal(err)
}
query := `
{
me(func: eq(email, "user@dgraph.io")) {
name
email
dgraph.type
}
}
`
resp, err := dg.NewTxn().Query(ctx, query)
if err != nil {
log.Fatal(err)
}
// resp.Json contains the updated value.
fmt.Println(string(resp.Json))
Output: {"me":[{"name":"user","email":"user@dgraph.io"}]}
Example (UpsertJSON) ¶
dg, cancel := getDgraphClient()
defer cancel()
// Warn: Cleaning up the database
ctx := context.Background()
if err := dg.Alter(ctx, &api.Operation{DropAll: true}); err != nil {
log.Fatal(err)
}
type Person struct {
Uid string `json:"uid,omitempty"`
Name string `json:"name,omitempty"`
Age int `json:"age,omitempty"`
Email string `json:"email,omitempty"`
Friends []Person `json:"friends,omitempty"`
DType []string `json:"dgraph.type,omitempty"`
}
op := &api.Operation{Schema: `email: string @index(exact) @upsert .`}
if err := dg.Alter(context.Background(), op); err != nil {
log.Fatal(err)
}
// Create and query the user using Upsert block
req := &api.Request{CommitNow: true}
req.Query = `
{
me(func: eq(email, "user@dgraph.io")) {
...fragmentA
}
}
fragment fragmentA {
v as uid
}
`
pb, err := json.Marshal(Person{Uid: "uid(v)", Name: "Wrong", Email: "user@dgraph.io"})
if err != nil {
log.Fatal(err)
}
mu := &api.Mutation{SetJson: pb}
req.Mutations = []*api.Mutation{mu}
if _, err := dg.NewTxn().Do(ctx, req); err != nil {
log.Fatal(err)
}
// Fix the name and add age
pb, err = json.Marshal(Person{Uid: "uid(v)", Name: "user", Age: 35})
if err != nil {
log.Fatal(err)
}
mu.SetJson = pb
req.Mutations = []*api.Mutation{mu}
if _, err := dg.NewTxn().Do(ctx, req); err != nil {
log.Fatal(err)
}
q := `
{
Me(func: has(email)) {
age
name
email
dgraph.type
}
}
`
resp, err := dg.NewReadOnlyTxn().Query(ctx, q)
if err != nil {
log.Fatal("The query should have succeeded")
}
type Root struct {
Me []Person `json:"me"`
}
var r Root
if err := json.Unmarshal(resp.Json, &r); err != nil {
log.Fatal(err)
}
fmt.Println(string(resp.Json))
// Delete the user now
mu.SetJson = nil
dgo.DeleteEdges(mu, "uid(v)", "age", "name", "email")
req.Mutations = []*api.Mutation{mu}
if _, err := dg.NewTxn().Do(ctx, req); err != nil {
log.Fatal(err)
}
resp, err = dg.NewReadOnlyTxn().Query(ctx, q)
if err != nil {
log.Fatal("The query should have succeeded")
}
if err := json.Unmarshal(resp.Json, &r); err != nil {
log.Fatal(err)
}
fmt.Println(string(resp.Json))
Output: {"Me":[{"age":35,"name":"user","email":"user@dgraph.io"}]} {"Me":[]}
func (*Txn) Query ¶
Query sends a query to one of the connected Dgraph instances. If no mutations need to be made in the same transaction, it's convenient to chain the method, e.g. NewTxn().Query(ctx, "...").
Example (Besteffort) ¶
dg, cancel := getDgraphClient()
defer cancel()
// NOTE: Best effort only works with read-only queries.
txn := dg.NewReadOnlyTxn().BestEffort()
resp, err := txn.Query(context.Background(), `{ q(func: uid(0x1)) { uid } }`)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(resp.Json))
Output: {"q":[{"uid":"0x1"}]}
Example (Unmarshal) ¶
type School struct {
Name string `json:"name,omitempty"`
DType []string `json:"dgraph.type,omitempty"`
}
type Person struct {
Uid string `json:"uid,omitempty"`
Name string `json:"name,omitempty"`
Age int `json:"age,omitempty"`
Married bool `json:"married,omitempty"`
Raw []byte `json:"raw_bytes,omitempty"`
Friends []Person `json:"friends,omitempty"`
School []School `json:"school,omitempty"`
DType []string `json:"dgraph.type,omitempty"`
}
dg, cancel := getDgraphClient()
defer cancel()
op := &api.Operation{}
op.Schema = `
name: string @index(exact) .
age: int .
married: bool .
Friends: [uid] .
type Person {
name
age
married
Friends
}
type Institution {
name
}
`
ctx := context.Background()
err := dg.Alter(ctx, op)
if err != nil {
log.Fatal(err)
}
p := Person{
Uid: "_:bob",
Name: "Bob",
Age: 24,
DType: []string{"Person"},
}
txn := dg.NewTxn()
pb, err := json.Marshal(p)
if err != nil {
log.Fatal(err)
}
mu := &api.Mutation{
CommitNow: true,
SetJson: pb,
}
response, err := txn.Mutate(ctx, mu)
if err != nil {
log.Fatal(err)
}
bob := response.Uids["bob"]
// While setting an object if a struct has a Uid then its properties
// in the graph are updated else a new node is created.
// In the example below new nodes for Alice and Charlie and school are created
// (since they dont have a Uid). Alice is also connected via the friend edge
// to an existing node Bob.
p = Person{
Uid: "_:alice",
Name: "Alice",
Age: 26,
Married: true,
DType: []string{"Person"},
Raw: []byte("raw_bytes"),
Friends: []Person{{
Uid: bob,
}, {
Name: "Charlie",
Age: 29,
DType: []string{"Person"},
}},
School: []School{{
Name: "Crown Public School",
DType: []string{"Institution"},
}},
}
txn = dg.NewTxn()
mu = &api.Mutation{}
pb, err = json.Marshal(p)
if err != nil {
log.Fatal(err)
}
mu.SetJson = pb
mu.CommitNow = true
response, err = txn.Mutate(ctx, mu)
if err != nil {
log.Fatal(err)
}
// Assigned uids for nodes which were created would be returned in the response.Uids map.
puid := response.Uids["alice"]
variables := make(map[string]string)
variables["$id"] = puid
const q = `
query Me($id: string){
me(func: uid($id)) {
name
age
loc
raw_bytes
married
dgraph.type
friends @filter(eq(name, "Bob")) {
name
age
dgraph.type
}
school {
name
dgraph.type
}
}
}
`
resp, err := dg.NewTxn().QueryWithVars(ctx, q, variables)
if err != nil {
log.Fatal(err)
}
type Root struct {
Me []Person `json:"me"`
}
var r Root
err = json.Unmarshal(resp.Json, &r)
if err != nil {
log.Fatal(err)
}
out, _ := json.MarshalIndent(r, "", "\t")
fmt.Printf("%s\n", out)
Output: { "me": [ { "name": "Alice", "age": 26, "married": true, "raw_bytes": "cmF3X2J5dGVz", "friends": [ { "name": "Bob", "age": 24, "dgraph.type": [ "Person" ] } ], "school": [ { "name": "Crown Public School", "dgraph.type": [ "Institution" ] } ], "dgraph.type": [ "Person" ] } ] }
Example (Variables) ¶
dg, cancel := getDgraphClient()
defer cancel()
type Person struct {
Uid string `json:"uid,omitempty"`
Name string `json:"name,omitempty"`
DType []string `json:"dgraph.type,omitempty"`
}
op := &api.Operation{}
op.Schema = `
name: string @index(exact) .
type Person {
name
}
`
ctx := context.Background()
err := dg.Alter(ctx, op)
if err != nil {
log.Fatal(err)
}
p := Person{
Name: "Alice",
DType: []string{"Person"},
}
mu := &api.Mutation{
CommitNow: true,
}
pb, err := json.Marshal(p)
if err != nil {
log.Fatal(err)
}
mu.SetJson = pb
_, err = dg.NewTxn().Mutate(ctx, mu)
if err != nil {
log.Fatal(err)
}
variables := make(map[string]string)
variables["$a"] = "Alice"
q := `
query Alice($a: string){
me(func: eq(name, $a)) {
name
dgraph.type
}
}
`
resp, err := dg.NewTxn().QueryWithVars(ctx, q, variables)
if err != nil {
log.Fatal(err)
}
type Root struct {
Me []Person `json:"me"`
}
var r Root
err = json.Unmarshal(resp.Json, &r)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(resp.Json))
Output: {"me":[{"name":"Alice","dgraph.type":["Person"]}]}
func (*Txn) QueryRDF ¶
QueryRDF sends a query to one of the connected Dgraph instances and returns RDF response. If no mutations need to be made in the same transaction, it's convenient to chain the method, e.g. NewTxn().QueryRDF(ctx, "...").
type TxnOption ¶
type TxnOption func(*txnOptions) error
TxnOption is a function that modifies the txn options.
func WithBestEffort ¶
func WithBestEffort() TxnOption
WithBestEffort sets the txn to be best effort.
func WithResponseFormat ¶
func WithResponseFormat(respFormat api.Request_RespFormat) TxnOption
WithResponseFormat sets the response format for queries. By default, the response format is JSON. We can also specify RDF format.