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) ¶
package main import ( "context" "fmt" "log" "github.com/dgraph-io/dgo" "github.com/dgraph-io/dgo/protos/api" "google.golang.org/grpc" ) func main() { conn, err := grpc.Dial("127.0.0.1:9180", grpc.WithInsecure()) if err != nil { log.Fatal("While trying to dial gRPC") } defer conn.Close() dc := api.NewDgraphClient(conn) dg := dgo.NewDgraphClient(dc) 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) ¶
package main import ( "context" "encoding/json" "fmt" "log" "time" "github.com/dgraph-io/dgo" "github.com/dgraph-io/dgo/protos/api" "google.golang.org/grpc" ) type School struct { Name string `json:"name,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"` } func main() { conn, err := grpc.Dial("127.0.0.1:9180", grpc.WithInsecure()) if err != nil { log.Fatal("While trying to dial gRPC") } defer conn.Close() dc := api.NewDgraphClient(conn) dg := dgo.NewDgraphClient(dc) 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 // dont have a Uid). p := Person{ Uid: "_:alice", Name: "Alice", Age: 26, Married: true, Location: loc{ Type: "Point", Coords: []float64{1.1, 2}, }, Dob: &dob, Raw: []byte("raw_bytes"), Friends: []Person{{ Name: "Bob", Age: 24, }, { Name: "Charlie", Age: 29, }}, School: []School{{ Name: "Crown Public School", }}, } 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) } mu := &api.Mutation{ CommitNow: true, } pb, err := json.Marshal(p) if err != nil { log.Fatal(err) } mu.SetJson = pb assigned, err := dg.NewTxn().Mutate(ctx, mu) if err != nil { log.Fatal(err) } // Assigned uids for nodes which were created would be returned in the assigned.Uids map. variables := map[string]string{"$id1": assigned.Uids["alice"]} q := `query Me($id1: string){ me(func: uid($id1)) { name dob age loc raw_bytes married friend @filter(eq(name, "Bob")){ name age } school { name } } }` 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.Printf("Me: %+v\n", r.Me) // R.Me would be same as the person that we set above. fmt.Println(string(resp.Json)) }
Output: {"me":[{"name":"Alice","dob":"1980-01-01T23:00:00Z","age":26,"loc":{"type":"Point","coordinates":[1.1,2]},"raw_bytes":"cmF3X2J5dGVz","married":true,"friend":[{"name":"Bob","age":24}],"school":[{"name":"Crown Public School"}]}]}
Index ¶
- Variables
- func DeleteEdges(mu *api.Mutation, uid string, predicates ...string)
- type Dgraph
- 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) Mutate(ctx context.Context, mu *api.Mutation) (*api.Assigned, error)
- func (txn *Txn) Query(ctx context.Context, q string) (*api.Response, error)
- func (txn *Txn) QueryWithVars(ctx context.Context, q string, vars map[string]string) (*api.Response, error)
- func (txn *Txn) Sequencing(sequencing api.LinRead_Sequencing)
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") )
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 ¶
package main import ( "context" "encoding/json" "fmt" "log" "strings" "time" "github.com/dgraph-io/dgo" "github.com/dgraph-io/dgo/protos/api" "google.golang.org/grpc" ) type CancelFunc func() func getDgraphClient() (*dgo.Dgraph, CancelFunc) { conn, err := grpc.Dial("127.0.0.1:9180", grpc.WithInsecure()) if err != nil { log.Fatal("While trying to dial gRPC") } dc := api.NewDgraphClient(conn) dg := dgo.NewDgraphClient(dc) ctx := context.Background() for { err = dg.Login(ctx, "groot", "password") if err == nil || !strings.Contains(err.Error(), "Please retry") { break } time.Sleep(time.Second) } if err != nil { log.Fatalf("While trying to login %v", err.Error()) } return dg, func() { if err := conn.Close(); err != nil { log.Printf("Error while closing connection:%v", err) } } } func main() { dg, cancel := getDgraphClient() defer cancel() op := &api.Operation{} op.Schema = ` age: int . married: bool . name: string @lang . location: string . ` 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"` } 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"` } // Lets add some data first. p := Person{ Uid: "_:alice", Name: "Alice", Age: 26, Married: true, Location: "Riley Street", Friends: []Person{{ Name: "Bob", Age: 24, }, { Name: "Charlie", Age: 29, }}, Schools: []*School{&School{ Name: "Crown Public School", }}, } mu := &api.Mutation{} pb, err := json.Marshal(p) if err != nil { log.Fatal(err) } mu.SetJson = pb mu.CommitNow = true mu.IgnoreIndexConflict = true assigned, err := dg.NewTxn().Mutate(ctx, mu) if err != nil { log.Fatal(err) } alice := assigned.Uids["alice"] variables := make(map[string]string) variables["$alice"] = alice const q = `query Me($alice: string){ me(func: uid($alice)) { name age location married friends { name age } schools { name@en } } }` 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 err = json.Unmarshal(resp.Json, &r) fmt.Println(string(resp.Json)) }
Output: {"me":[{"name":"Alice","age":26,"married":true,"schools":[{"name@en":"Crown Public School"}]}]}
Types ¶
type Dgraph ¶
type Dgraph struct {
// contains filtered or unexported fields
}
Dgraph is a transaction aware client to a set of Dgraph server instances.
func NewDgraphClient ¶
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.
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.
Example (DropAll) ¶
package main import ( "context" "log" "strings" "time" "github.com/dgraph-io/dgo" "github.com/dgraph-io/dgo/protos/api" "google.golang.org/grpc" ) type CancelFunc func() func getDgraphClient() (*dgo.Dgraph, CancelFunc) { conn, err := grpc.Dial("127.0.0.1:9180", grpc.WithInsecure()) if err != nil { log.Fatal("While trying to dial gRPC") } dc := api.NewDgraphClient(conn) dg := dgo.NewDgraphClient(dc) ctx := context.Background() for { err = dg.Login(ctx, "groot", "password") if err == nil || !strings.Contains(err.Error(), "Please retry") { break } time.Sleep(time.Second) } if err != nil { log.Fatalf("While trying to login %v", err.Error()) } return dg, func() { if err := conn.Close(); err != nil { log.Printf("Error while closing connection:%v", err) } } } func main() { dg, cancel := getDgraphClient() defer cancel() op := api.Operation{DropAll: true} ctx := context.Background() if err := dg.Alter(ctx, &op); err != nil { log.Fatal(err) } }
Output:
func (*Dgraph) Login ¶
Login 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.
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 ¶
package main import ( "context" "fmt" "log" "strings" "time" "github.com/dgraph-io/dgo" "github.com/dgraph-io/dgo/protos/api" "google.golang.org/grpc" ) type CancelFunc func() func getDgraphClient() (*dgo.Dgraph, CancelFunc) { conn, err := grpc.Dial("127.0.0.1:9180", grpc.WithInsecure()) if err != nil { log.Fatal("While trying to dial gRPC") } dc := api.NewDgraphClient(conn) dg := dgo.NewDgraphClient(dc) ctx := context.Background() for { err = dg.Login(ctx, "groot", "password") if err == nil || !strings.Contains(err.Error(), "Please retry") { break } time.Sleep(time.Second) } if err != nil { log.Fatalf("While trying to login %v", err.Error()) } return dg, func() { if err := conn.Close(); err != nil { log.Printf("Error while closing connection:%v", err) } } } func main() { 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") } txn.Discard(ctx) // now query the cluster and make sure that the data has made no effect queryTxn := dg.NewReadOnlyTxn() query := ` { q (func: eq(name, "Alice")) { name } }` resp, err := queryTxn.Query(ctx, query) if err != nil { log.Fatal("The query should have succeeded") } fmt.Printf(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 ¶
package main import ( "context" "encoding/json" "fmt" "log" "strings" "time" "github.com/dgraph-io/dgo" "github.com/dgraph-io/dgo/protos/api" "google.golang.org/grpc" ) type CancelFunc func() func getDgraphClient() (*dgo.Dgraph, CancelFunc) { conn, err := grpc.Dial("127.0.0.1:9180", grpc.WithInsecure()) if err != nil { log.Fatal("While trying to dial gRPC") } dc := api.NewDgraphClient(conn) dg := dgo.NewDgraphClient(dc) ctx := context.Background() for { err = dg.Login(ctx, "groot", "password") if err == nil || !strings.Contains(err.Error(), "Please retry") { break } time.Sleep(time.Second) } if err != nil { log.Fatalf("While trying to login %v", err.Error()) } return dg, func() { if err := conn.Close(); err != nil { log.Printf("Error while closing connection:%v", err) } } } func main() { type School struct { Name string `json:"name,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:"friend,omitempty"` Location loc `json:"loc,omitempty"` School []School `json:"school,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, Location: loc{ Type: "Point", Coords: []float64{1.1, 2}, }, Raw: []byte("raw_bytes"), Friends: []Person{{ Name: "Bob", Age: 24, }, { Name: "Charlie", Age: 29, }}, School: []School{{ Name: "Crown Public School", }}, } op := &api.Operation{} op.Schema = ` age: int . married: bool . ` 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 assigned, err := dg.NewTxn().Mutate(ctx, mu) if err != nil { log.Fatal(err) } // Assigned uids for nodes which were created would be returned in the assigned.Uids map. puid := assigned.Uids["alice"] const q = `query Me($id: string){ me(func: uid($id)) { name age loc raw_bytes married friend @filter(eq(name, "Bob")) { name age } school { name } } }` 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) } // R.Me would be same as the person that we set above. // fmt.Printf("Me: %+v\n", r.Me) fmt.Println(string(resp.Json)) }
Output: {"me":[{"name":"Alice","age":26,"loc":{"type":"Point","coordinates":[1.1,2]},"raw_bytes":"cmF3X2J5dGVz","married":true,"friend":[{"name":"Bob","age":24}],"school":[{"name":"Crown Public School"}]}]}
Example (Bytes) ¶
package main import ( "context" "encoding/json" "fmt" "log" "strings" "time" "github.com/dgraph-io/dgo" "github.com/dgraph-io/dgo/protos/api" "google.golang.org/grpc" ) type CancelFunc func() func getDgraphClient() (*dgo.Dgraph, CancelFunc) { conn, err := grpc.Dial("127.0.0.1:9180", grpc.WithInsecure()) if err != nil { log.Fatal("While trying to dial gRPC") } dc := api.NewDgraphClient(conn) dg := dgo.NewDgraphClient(dc) ctx := context.Background() for { err = dg.Login(ctx, "groot", "password") if err == nil || !strings.Contains(err.Error(), "Please retry") { break } time.Sleep(time.Second) } if err != nil { log.Fatalf("While trying to login %v", err.Error()) } return dg, func() { if err := conn.Close(); err != nil { log.Printf("Error while closing connection:%v", err) } } } func main() { dg, cancel := getDgraphClient() defer cancel() type Person struct { Uid string `json:"uid,omitempty"` Name string `json:"name,omitempty"` Bytes []byte `json:"bytes,omitempty"` } op := &api.Operation{} op.Schema = ` name: string @index(exact) . ` ctx := context.Background() err := dg.Alter(ctx, op) if err != nil { log.Fatal(err) } p := Person{ Name: "Alice-new", 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 } }` 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]}]
Example (DeleteNode) ¶
package main import ( "context" "encoding/json" "fmt" "log" "strings" "time" "github.com/dgraph-io/dgo" "github.com/dgraph-io/dgo/protos/api" "google.golang.org/grpc" ) type CancelFunc func() func getDgraphClient() (*dgo.Dgraph, CancelFunc) { conn, err := grpc.Dial("127.0.0.1:9180", grpc.WithInsecure()) if err != nil { log.Fatal("While trying to dial gRPC") } dc := api.NewDgraphClient(conn) dg := dgo.NewDgraphClient(dc) ctx := context.Background() for { err = dg.Login(ctx, "groot", "password") if err == nil || !strings.Contains(err.Error(), "Please retry") { break } time.Sleep(time.Second) } if err != nil { log.Fatalf("While trying to login %v", err.Error()) } return dg, func() { if err := conn.Close(); err != nil { log.Printf("Error while closing connection:%v", err) } } } func main() { 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:"friend,omitempty"` DgraphType string `json:"dgraph.type,omitempty"` } p := Person{ Uid: "_:alice", Name: "Alice", Age: 26, Married: true, DgraphType: "Person", Friends: []*Person{&Person{ Uid: "_:bob", Name: "Bob", Age: 24, }, &Person{ Uid: "_:charlie", Name: "Charlie", Age: 29, }}, } op := &api.Operation{} op.Schema = ` age: int . married: bool . type Person { name: string age: int married: bool friend: [uid] } ` 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 assigned, err := dg.NewTxn().Mutate(ctx, mu) if err != nil { log.Fatal(err) } alice := assigned.Uids["alice"] bob := assigned.Uids["bob"] charlie := assigned.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 friend { uid name age } } me2(func: uid($bob)) { name age } me3(func: uid($charlie)) { name age } }` 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 err = json.Unmarshal(resp.Json, &r) // 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) } fmt.Printf("Resp after deleting node: %+v\n", string(resp.Json)) }
Output: Resp after deleting node: {"me":[],"me2":[{"name":"Bob","age":24}],"me3":[{"name":"Charlie","age":29}]}
Example (DeletePredicate) ¶
package main import ( "context" "encoding/json" "fmt" "log" "strings" "time" "github.com/dgraph-io/dgo" "github.com/dgraph-io/dgo/protos/api" "google.golang.org/grpc" ) type CancelFunc func() func getDgraphClient() (*dgo.Dgraph, CancelFunc) { conn, err := grpc.Dial("127.0.0.1:9180", grpc.WithInsecure()) if err != nil { log.Fatal("While trying to dial gRPC") } dc := api.NewDgraphClient(conn) dg := dgo.NewDgraphClient(dc) ctx := context.Background() for { err = dg.Login(ctx, "groot", "password") if err == nil || !strings.Contains(err.Error(), "Please retry") { break } time.Sleep(time.Second) } if err != nil { log.Fatalf("While trying to login %v", err.Error()) } return dg, func() { if err := conn.Close(); err != nil { log.Printf("Error while closing connection:%v", err) } } } func main() { 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:"friend,omitempty"` } p := Person{ Uid: "_:alice", Name: "Alice", Age: 26, Married: true, Friends: []Person{Person{ Name: "Bob", Age: 24, }, Person{ Name: "Charlie", Age: 29, }}, } op := &api.Operation{} op.Schema = ` age: int . married: bool . ` 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 assigned, err := dg.NewTxn().Mutate(ctx, mu) if err != nil { log.Fatal(err) } alice := assigned.Uids["alice"] variables := make(map[string]string) variables["$id"] = alice const q = `query Me($id: string){ me(func: uid($id)) { name age married friend { uid name age } } }` 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: "friend"} 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("Response after deletion: %+v\n", r) }
Output: Response after deletion: {Me:[{Uid: Name:Alice Age:26 Married:false Friends:[]}]}
Example (Facets) ¶
package main import ( "context" "encoding/json" "fmt" "log" "strings" "time" "github.com/dgraph-io/dgo" "github.com/dgraph-io/dgo/protos/api" "google.golang.org/grpc" ) type CancelFunc func() func getDgraphClient() (*dgo.Dgraph, CancelFunc) { conn, err := grpc.Dial("127.0.0.1:9180", grpc.WithInsecure()) if err != nil { log.Fatal("While trying to dial gRPC") } dc := api.NewDgraphClient(conn) dg := dgo.NewDgraphClient(dc) ctx := context.Background() for { err = dg.Login(ctx, "groot", "password") if err == nil || !strings.Contains(err.Error(), "Please retry") { break } time.Sleep(time.Second) } if err != nil { log.Fatalf("While trying to login %v", err.Error()) } return dg, func() { if err := conn.Close(); err != nil { log.Printf("Error while closing connection:%v", err) } } } func main() { 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) . ` 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"` } type Person struct { Uid string `json:"uid,omitempty"` Name string `json:"name,omitempty"` NameOrigin string `json:"name|origin,omitempty"` Friends []Person `json:"friend,omitempty"` // These are facets on the friend edge. Since time.Time `json:"friend|since,omitempty"` Family string `json:"friend|family,omitempty"` Age float64 `json:"friend|age,omitempty"` Close bool `json:"friend|close,omitempty"` School []School `json:"school,omitempty"` } ti := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC) p := Person{ Uid: "_:alice", Name: "Alice", NameOrigin: "Indonesia", Friends: []Person{ Person{ Name: "Bob", Since: ti, Family: "yes", Age: 13, Close: true, }, Person{ Name: "Charlie", Family: "maybe", Age: 16, }, }, School: []School{School{ Name: "Wellington School", Since: ti, }}, } mu := &api.Mutation{} pb, err := json.Marshal(p) if err != nil { log.Fatal(err) } mu.SetJson = pb mu.CommitNow = true assigned, err := dg.NewTxn().Mutate(ctx, mu) if err != nil { log.Fatal(err) } auid := assigned.Uids["alice"] variables := make(map[string]string) variables["$id"] = auid const q = `query Me($id: string){ me(func: uid($id)) { name @facets friend @filter(eq(name, "Bob")) @facets { name } school @facets { name } } }` 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.Printf("Me: %+v\n", r.Me) }
Output: Me: [{Uid: Name:Alice NameOrigin:Indonesia Friends:[{Uid: Name:Bob NameOrigin: Friends:[] Since:2009-11-10 23:00:00 +0000 UTC Family:yes Age:13 Close:true School:[]}] Since:0001-01-01 00:00:00 +0000 UTC Family: Age:0 Close:false School:[{Name:Wellington School Since:2009-11-10 23:00:00 +0000 UTC}]}]
Example (List) ¶
package main import ( "context" "encoding/json" "fmt" "log" "strings" "time" "github.com/dgraph-io/dgo" "github.com/dgraph-io/dgo/protos/api" "google.golang.org/grpc" ) type CancelFunc func() func getDgraphClient() (*dgo.Dgraph, CancelFunc) { conn, err := grpc.Dial("127.0.0.1:9180", grpc.WithInsecure()) if err != nil { log.Fatal("While trying to dial gRPC") } dc := api.NewDgraphClient(conn) dg := dgo.NewDgraphClient(dc) ctx := context.Background() for { err = dg.Login(ctx, "groot", "password") if err == nil || !strings.Contains(err.Error(), "Please retry") { break } time.Sleep(time.Second) } if err != nil { log.Fatalf("While trying to login %v", err.Error()) } return dg, func() { if err := conn.Close(); err != nil { log.Printf("Error while closing connection:%v", err) } } } func main() { 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"` } p := Person{ Address: []string{"Redfern", "Riley Street"}, PhoneNumber: []int64{9876, 123}, } op := &api.Operation{} op.Schema = ` address: [string] . phone_number: [int] . ` 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 assigned, err := dg.NewTxn().Mutate(ctx, mu) if err != nil { log.Fatal(err) } variables := map[string]string{"$id": assigned.Uids["blank-0"]} const q = ` query Me($id: string){ me(func: uid($id)) { address phone_number } } ` 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]}]} }
Output:
Example (Upsert) ¶
package main import ( "context" "fmt" "log" "strings" "time" "github.com/dgraph-io/dgo" "github.com/dgraph-io/dgo/protos/api" "google.golang.org/grpc" ) type CancelFunc func() func getDgraphClient() (*dgo.Dgraph, CancelFunc) { conn, err := grpc.Dial("127.0.0.1:9180", grpc.WithInsecure()) if err != nil { log.Fatal("While trying to dial gRPC") } dc := api.NewDgraphClient(conn) dg := dgo.NewDgraphClient(dc) ctx := context.Background() for { err = dg.Login(ctx, "groot", "password") if err == nil || !strings.Contains(err.Error(), "Please retry") { break } time.Sleep(time.Second) } if err != nil { log.Fatalf("While trying to login %v", err.Error()) } return dg, func() { if err := conn.Close(); err != nil { log.Printf("Error while closing connection:%v", err) } } } func main() { 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) } mu.Query = ` query { me(func: eq(email, "user@dgraphO.io")) { v as uid } } ` m2 := `uid(v) <email> "user@dgraph.io" .` mu.SetNquads = []byte(m2) // Update email only if matching uid found. if _, err := dg.NewTxn().Mutate(ctx, mu); err != nil { log.Fatal(err) } query := ` { me(func: eq(email, "user@dgraph.io")) { name email } } ` 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) ¶
package main import ( "context" "encoding/json" "fmt" "log" "strings" "time" "github.com/dgraph-io/dgo" "github.com/dgraph-io/dgo/protos/api" "google.golang.org/grpc" ) type CancelFunc func() func getDgraphClient() (*dgo.Dgraph, CancelFunc) { conn, err := grpc.Dial("127.0.0.1:9180", grpc.WithInsecure()) if err != nil { log.Fatal("While trying to dial gRPC") } dc := api.NewDgraphClient(conn) dg := dgo.NewDgraphClient(dc) ctx := context.Background() for { err = dg.Login(ctx, "groot", "password") if err == nil || !strings.Contains(err.Error(), "Please retry") { break } time.Sleep(time.Second) } if err != nil { log.Fatalf("While trying to login %v", err.Error()) } return dg, func() { if err := conn.Close(); err != nil { log.Printf("Error while closing connection:%v", err) } } } func main() { 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:"friend,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 mu := &api.Mutation{CommitNow: true} mu.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.SetJson = pb if _, err := dg.NewTxn().Mutate(ctx, mu); 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 if _, err := dg.NewTxn().Mutate(ctx, mu); err != nil { log.Fatal(err) } q := ` { Me(func: has(email)) { age name email } } ` 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") if _, err := dg.NewTxn().Mutate(ctx, mu); 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) ¶
package main import ( "context" "fmt" "log" "strings" "time" "github.com/dgraph-io/dgo" "github.com/dgraph-io/dgo/protos/api" "google.golang.org/grpc" ) type CancelFunc func() func getDgraphClient() (*dgo.Dgraph, CancelFunc) { conn, err := grpc.Dial("127.0.0.1:9180", grpc.WithInsecure()) if err != nil { log.Fatal("While trying to dial gRPC") } dc := api.NewDgraphClient(conn) dg := dgo.NewDgraphClient(dc) ctx := context.Background() for { err = dg.Login(ctx, "groot", "password") if err == nil || !strings.Contains(err.Error(), "Please retry") { break } time.Sleep(time.Second) } if err != nil { log.Fatalf("While trying to login %v", err.Error()) } return dg, func() { if err := conn.Close(); err != nil { log.Printf("Error while closing connection:%v", err) } } } func main() { 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) ¶
package main import ( "context" "encoding/json" "fmt" "log" "strings" "time" "github.com/dgraph-io/dgo" "github.com/dgraph-io/dgo/protos/api" "google.golang.org/grpc" ) type CancelFunc func() func getDgraphClient() (*dgo.Dgraph, CancelFunc) { conn, err := grpc.Dial("127.0.0.1:9180", grpc.WithInsecure()) if err != nil { log.Fatal("While trying to dial gRPC") } dc := api.NewDgraphClient(conn) dg := dgo.NewDgraphClient(dc) ctx := context.Background() for { err = dg.Login(ctx, "groot", "password") if err == nil || !strings.Contains(err.Error(), "Please retry") { break } time.Sleep(time.Second) } if err != nil { log.Fatalf("While trying to login %v", err.Error()) } return dg, func() { if err := conn.Close(); err != nil { log.Printf("Error while closing connection:%v", err) } } } func main() { type School struct { Name string `json:"name,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:"friend,omitempty"` School []School `json:"school,omitempty"` } dg, cancel := getDgraphClient() defer cancel() op := &api.Operation{} op.Schema = ` age: int . married: bool . ` ctx := context.Background() err := dg.Alter(ctx, op) if err != nil { log.Fatal(err) } p := Person{ Uid: "_:bob", Name: "Bob", Age: 24, } txn := dg.NewTxn() pb, err := json.Marshal(p) if err != nil { log.Fatal(err) } mu := &api.Mutation{ CommitNow: true, SetJson: pb, } assigned, err := txn.Mutate(ctx, mu) if err != nil { log.Fatal(err) } bob := assigned.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, Raw: []byte("raw_bytes"), Friends: []Person{{ Uid: bob, }, { Name: "Charlie", Age: 29, }}, School: []School{{ Name: "Crown Public School", }}, } txn = dg.NewTxn() mu = &api.Mutation{} pb, err = json.Marshal(p) if err != nil { log.Fatal(err) } mu.SetJson = pb mu.CommitNow = true assigned, err = txn.Mutate(ctx, mu) if err != nil { log.Fatal(err) } // Assigned uids for nodes which were created would be returned in the assigned.Uids map. puid := assigned.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 friend @filter(eq(name, "Bob")) { name age } school { name } } }` 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","age":26,"raw_bytes":"cmF3X2J5dGVz","married":true,"friend":[{"name":"Bob","age":24}],"school":[{"name":"Crown Public School"}]}]}
Example (Variables) ¶
package main import ( "context" "encoding/json" "fmt" "log" "strings" "time" "github.com/dgraph-io/dgo" "github.com/dgraph-io/dgo/protos/api" "google.golang.org/grpc" ) type CancelFunc func() func getDgraphClient() (*dgo.Dgraph, CancelFunc) { conn, err := grpc.Dial("127.0.0.1:9180", grpc.WithInsecure()) if err != nil { log.Fatal("While trying to dial gRPC") } dc := api.NewDgraphClient(conn) dg := dgo.NewDgraphClient(dc) ctx := context.Background() for { err = dg.Login(ctx, "groot", "password") if err == nil || !strings.Contains(err.Error(), "Please retry") { break } time.Sleep(time.Second) } if err != nil { log.Fatalf("While trying to login %v", err.Error()) } return dg, func() { if err := conn.Close(); err != nil { log.Printf("Error while closing connection:%v", err) } } } func main() { dg, cancel := getDgraphClient() defer cancel() type Person struct { Uid string `json:"uid,omitempty"` Name string `json:"name,omitempty"` } op := &api.Operation{} op.Schema = ` name: string @index(exact) . ` ctx := context.Background() err := dg.Alter(ctx, op) if err != nil { log.Fatal(err) } p := Person{ Name: "Alice", } 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 } }` 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"}]}
func (*Txn) QueryWithVars ¶
func (txn *Txn) QueryWithVars(ctx context.Context, q string, vars map[string]string) ( *api.Response, error)
QueryWithVars is like Query, but allows a variable map to be used. This can provide safety against injection attacks.
func (*Txn) Sequencing ¶
func (txn *Txn) Sequencing(sequencing api.LinRead_Sequencing)
Sequencing is no longer used