Skip to content
Snippets Groups Projects
Commit 69964c29 authored by MichaelJCompton's avatar MichaelJCompton
Browse files

go docs update

parent 07abc9a2
No related branches found
No related tags found
No related merge requests found
......@@ -28,22 +28,24 @@ import (
"github.com/twpayne/go-geom/encoding/geojson"
)
type Op int
type opType int
const (
// SET indicates a Set mutation.
SET Op = iota
SET opType = iota
// DEL indicates a Delete mutation.
DEL
)
// Req wraps the protos.Request so that helper methods can be defined on it.
// A Req represents a single request to the backend Dgraph instance. Each request may contain multiple set, delete and
// schema mutations, and a single GraphQL+- query. IF the query contains GraphQL variables, then the map giving values to these
// must be stored in the request with the query.
type Req struct {
gr protos.Request
}
// Request returns the graph request object which is sent to the server to perform
// a query/mutation.
// Request returns the protos.Request backing the Req.
func (req *Req) Request() *protos.Request {
return &req.gr
}
......@@ -61,18 +63,23 @@ func checkSchema(schema protos.SchemaUpdate) error {
return nil
}
// SetQuery sets a query with graphQL variables as part of the request.
// SetQuery sets the query in req to the given string.
// The query string is not checked until the request is
// run, when it is parsed and checked server-side.
func (req *Req) SetQuery(q string) {
req.gr.Query = q
}
// SetQueryWithVariables sets a query with graphQL variables as part of the request.
// SetQueryWithVariables sets query q (which contains graphQL variables mapped
// in vars) as the query in req and sets vars as the corresponding query variables.
// Neither the query string nor the variables are checked until the request is run,
// when it is parsed and checked server-side.
func (req *Req) SetQueryWithVariables(q string, vars map[string]string) {
req.gr.Query = q
req.gr.Vars = vars
}
func (req *Req) addMutation(e Edge, op Op) {
func (req *Req) addMutation(e Edge, op opType) {
if req.gr.Mutation == nil {
req.gr.Mutation = new(protos.Mutation)
}
......@@ -84,10 +91,18 @@ func (req *Req) addMutation(e Edge, op Op) {
}
}
// Set adds edge e to the set mutation of request req, thus scheduling the edge to be added to the graph when the request is run.
// The edge must be syntatically valid: have a valid source (a Node), predicate and target (a Node or value), otherwise an error is returned.
// The edge is not checked agaist the schema until the request is run --- so setting a UID edge to a value, for example, doesn't result in an
// error until the request is run.
func (req *Req) Set(e Edge) {
req.addMutation(e, SET)
}
// Delete adds edge e to the delete mutation of request req, thus scheduling the edge to be removed from the graph when the request is run.
// The edge must have a valid source (a Node), predicate and target (a Node or value), otherwise an error is returned. The edge need not represent
// an edge in the graph --- applying such a mutation simply has no effect.
func (req *Req) Delete(e Edge) {
req.addMutation(e, DEL)
}
......@@ -117,15 +132,17 @@ func (req *Req) reset() {
type nquadOp struct {
e Edge
op Op
op opType
}
// Node representes a single node in the graph.
type Node struct {
uid uint64
// We can do variables in mutations.
varName string
}
// String returns Node n as a string
func (n Node) String() string {
if n.uid != 0 {
return fmt.Sprintf("%#x", uint64(n.uid))
......@@ -133,6 +150,7 @@ func (n Node) String() string {
return n.varName
}
// ConnectTo creates an edge labelled pred from Node n to Node n1
func (n *Node) ConnectTo(pred string, n1 Node) Edge {
e := Edge{}
if len(n.varName) != 0 {
......@@ -145,6 +163,11 @@ func (n *Node) ConnectTo(pred string, n1 Node) Edge {
return e
}
// Edge create an edge with source Node n and predicate pred, but without a target.
// The edge needs to be completed by calling Edge.ConnectTo() if the edge is a
// UID edge, or one of the Edge.SetValue...() functions if the edge is of a scalar type.
// The edge can't be commited to the store --- calling Req.Set() to add the edge to
// a request will result in an error --- until it is completed.
func (n *Node) Edge(pred string) Edge {
e := Edge{}
if len(n.varName) != 0 {
......@@ -156,14 +179,23 @@ func (n *Node) Edge(pred string) Edge {
return e
}
// An Edge represents an edge between a source node and a target (either a node or a value.)
// Facets are stored in the edge. See Node.Edge(), Node.ConnectTo(), Edge.ConnecTo(),
// Edge.AddFacet and the Edge.SetValue...() functions to
// make a valid edge for a set or delete mutation.
type Edge struct {
nq protos.NQuad
}
// NewEdge creates and Edge from an NQuad.
func NewEdge(nq protos.NQuad) Edge {
return Edge{nq}
}
// ConnectTo adds Node n as the target of the edge. If the edge already has a known scalar type,
// for example if Edge.SetValue...() had been called on the edge, then an error is returned.
func (e *Edge) ConnectTo(n Node) error {
if e.nq.ObjectType > 0 {
return ErrValue
......@@ -185,6 +217,11 @@ func validateStr(val string) error {
return nil
}
// SetValueString sets the value of Edge e as string val and sets the type of the edge to types.StringID.
// If the edge had previous been assigned another value (even of another type), the value and type are overwritten.
// If the edge has previously been connected to a node, the edge and type are left unchanged and ErrConnected is returned.
// The string must escape " with \, otherwise the edge and type are left unchanged and an error returned.
func (e *Edge) SetValueString(val string) error {
if len(e.nq.ObjectId) > 0 {
return ErrConnected
......@@ -202,6 +239,10 @@ func (e *Edge) SetValueString(val string) error {
return nil
}
// SetValueInt sets the value of Edge e as int64 val and sets the type of the edge to types.IntID.
// If the edge had previous been assigned another value (even of another type), the value and type are overwritten.
// If the edge has previously been connected to a node, the edge and type are left unchanged and ErrConnected is returned.
func (e *Edge) SetValueInt(val int64) error {
if len(e.nq.ObjectId) > 0 {
return ErrConnected
......@@ -215,6 +256,9 @@ func (e *Edge) SetValueInt(val int64) error {
return nil
}
// SetValueFloat sets the value of Edge e as float64 val and sets the type of the edge to types.FloatID.
// If the edge had previous been assigned another value (even of another type), the value and type are overwritten.
// If the edge has previously been connected to a node, the edge and type are left unchanged and ErrConnected is returned.
func (e *Edge) SetValueFloat(val float64) error {
if len(e.nq.ObjectId) > 0 {
return ErrConnected
......@@ -228,6 +272,10 @@ func (e *Edge) SetValueFloat(val float64) error {
return nil
}
// SetValueBool sets the value of Edge e as bool val and sets the type of the edge to types.BoolID.
// If the edge had previous been assigned another value (even of another type), the value and type are overwritten.
// If the edge has previously been connected to a node, the edge and type are left unchanged and ErrConnected is returned.
func (e *Edge) SetValueBool(val bool) error {
if len(e.nq.ObjectId) > 0 {
return ErrConnected
......@@ -241,6 +289,10 @@ func (e *Edge) SetValueBool(val bool) error {
return nil
}
// SetValuePassword sets the value of Edge e as password string val and sets the type of the edge to types.PasswordID.
// If the edge had previous been assigned another value (even of another type), the value and type are overwritten.
// If the edge has previously been connected to a node, the edge and type are left unchanged and ErrConnected is returned.
func (e *Edge) SetValuePassword(val string) error {
if len(e.nq.ObjectId) > 0 {
return ErrConnected
......@@ -254,6 +306,10 @@ func (e *Edge) SetValuePassword(val string) error {
return nil
}
// SetValueDatetime sets the value of Edge e as time.Time dateTime and sets the type of the edge to types.DateTimeID.
// If the edge had previous been assigned another value (even of another type), the value and type are overwritten.
// If the edge has previously been connected to a node, the edge and type are left unchanged and ErrConnected is returned.
func (e *Edge) SetValueDatetime(dateTime time.Time) error {
if len(e.nq.ObjectId) > 0 {
return ErrConnected
......@@ -267,6 +323,12 @@ func (e *Edge) SetValueDatetime(dateTime time.Time) error {
return nil
}
// SetValueGeoJson sets the value of Edge e as the GeoJSON object parsed from json string and sets the type of the edge to types.GeoID.
// If the edge had previous been assigned another value (even of another type), the value and type are overwritten.
// If the edge has previously been connected to a node, the edge and type are left unchanged and ErrConnected is returned.
// If the string fails to parse with geojson.Unmarshal() the edge is left unchanged and an error returned.
func (e *Edge) SetValueGeoJson(json string) error {
if len(e.nq.ObjectId) > 0 {
return ErrConnected
......@@ -288,6 +350,12 @@ func (e *Edge) SetValueGeoJson(json string) error {
return nil
}
// SetValueDefault sets the value of Edge e as string val and sets the type of the edge to types.DefaultID.
// If the edge had previous been assigned another value (even of another type), the value and type are overwritten.
// If the edge has previously been connected to a node, the edge and type are left unchanged and ErrConnected is returned.
// The string must escape " with \, otherwise the edge and type are left unchanged and an error returned.
func (e *Edge) SetValueDefault(val string) error {
if len(e.nq.ObjectId) > 0 {
return ErrConnected
......@@ -305,6 +373,11 @@ func (e *Edge) SetValueDefault(val string) error {
return nil
}
// SetValueBytes allows setting the value of an edge to raw bytes and sets the type of the edge to types.BinaryID.
// If the edge had previous been assigned another value (even of another type), the value and type are overwritten.
// If the edge has previously been connected to a node, the edge and type are left unchanged and ErrConnected is returned.
// the bytes are encoded as base64.
func (e *Edge) SetValueBytes(val []byte) error {
if len(e.nq.ObjectId) > 0 {
return ErrConnected
......@@ -320,6 +393,7 @@ func (e *Edge) SetValueBytes(val []byte) error {
return nil
}
// AddFacet adds the key, value pair as facets on Edge e. No checking is done.
func (e *Edge) AddFacet(key, val string) {
e.nq.Facets = append(e.nq.Facets, &protos.Facet{
Key: key,
......
......@@ -14,102 +14,35 @@
* limitations under the License.
*/
/*
Package client provides helper function for interacting with the Dgraph server.
You can use it to run mutations and queries. You can also use BatchMutation
to upload data concurrently. It communicates with the server using gRPC.
In this example, we first create a node, add a name (Steven Spielberg) and age
attribute to it. We then create another node, add a name attribute (William Jones),
we then add a friend edge between the two nodes.
conn, err := grpc.Dial("127.0.0.1:9080", grpc.WithInsecure())
dgraphClient := protos.NewDgraphClient(conn)
req := client.Req{}
nq := protos.NQuad{
Subject: "_:person1",
Predicate: "name",
}
client.Str("Steven Spielberg", &nq)
req.AddMutation(nq, client.SET)
nq = protos.NQuad{
Subject: "_:person1",
Predicate: "age",
}
if err = client.Int(25, &nq); err != nil {
log.Fatal(err)
}
req.AddMutation(nq, client.SET)
nq = protos.NQuad{
Subject: "_:person2",
Predicate: "name",
}
client.Str("William Jones", &nq)
req.AddMutation(nq, client.SET)
/*
Package client is used to interact with a Dgraph server. Queries and
mutations can be run from the client. There are esentially two modes
of client interaction:
nq = protos.NQuad{
Subject: "_:person1",
Predicate: "friend",
ObjectId: "_:person2",
}
req.AddMutation(nq, client.SET)
- Request based interaction mode where the client builds requests and recieves
responses immediately after running, and
resp, err := dgraphClient.Run(context.Background(), req.Request())
if err != nil {
log.Fatalf("Error in getting response from server, %s", err)
}
- Batch mode where clients submit many requests and let the client package
batch those requests to the server.
Request Mode:
Dgraph would have assigned uids to these nodes.
See https://docs.dgraph.io/master/query-language/#assigning-uid for more details
on how assigning a new uid works.
We now query for these things.
person1Uid := resp.AssignedUids["person1"]
person2Uid := resp.AssignedUids["person2"]
req = client.Req{}
req.SetQuery(fmt.Sprintf(`
{
me(id: %v) {
_uid_
name
age
friend {
_uid_
name
}
}
}`, client.Uid(person1Uid)))
resp, err = dgraphClient.Run(context.Background(), req.Request())
if err != nil {
log.Fatalf("Error in getting response from server, %s", err)
}
Batch Mode: On creating a new client with NewDgraphClient users submit
BatchMutationOptions specifying the size of batches and number of concurrent
batches. Edges are added to the batch with BatchSet; deletions are added
with BatchDelete; and schema mutations with AddSchema.
person1 := resp.N[0].Children[0]
props := person1.Properties
name := props[0].Value.GetStrVal()
fmt.Println("Name: ", name)
Submitted mutations are nondeterministically added to batches and there are
no guarantees about which batch a mutation will be scheduled for (e.g. two
successive calls to BatchSet won't guarantee the edges to be in the same batch).
fmt.Println("Age: ", props[1].Value.GetIntVal())
Finishing and interaction with BatchFlush flushes all buffers and ends the
client interaction.
person2 := person1.Children[0]
fmt.Printf("%v name: %v\n", person2.Attribute, person2.Properties[0].Value.GetStrVal())
This is how we delete the friend edge between the two nodes.
nq = protos.NQuad{
Subject: client.Uid(person1Uid),
Predicate: "friend",
ObjectId: client.Uid(person2Uid),
}
req = client.Req{}
req.AddMutation(nq, client.DEL)
resp, err = dgraphClient.Run(context.Background(), req.Request())
if err != nil {
log.Fatalf("Error in getting response from server, %s", err)
}
For more details checkout https://docs.dgraph.io/master/clients/#go.
For more details checkout https://docs.dgraph.io/clients/#go.
*/
package client
......@@ -47,18 +47,23 @@ var (
emptyEdge Edge
)
var DefaultOptions = BatchMutationOptions{
Size: 100,
Pending: 100,
PrintCounters: false,
}
// BatchMutationOptions sets the clients batch mode to Pending number of buffers
// each of Size. Running counters of number of rdfs procesessed, total time and
// mutations per second are printed if PrintCounters is set true.
// See Counter.
type BatchMutationOptions struct {
Size int
Pending int
PrintCounters bool
}
var DefaultOptions = BatchMutationOptions{
Size: 100,
Pending: 100,
PrintCounters: false,
}
type allocator struct {
x.SafeMutex
......@@ -148,6 +153,8 @@ func (a *allocator) assignOrGet(id string) (uid uint64, isNew bool, err error) {
}
// Counter keeps a track of various parameters about a batch mutation.
// Running totals are printed if BatchMutationOptions
// PrintCounters is set to true.
type Counter struct {
// Number of RDF's processed by server.
Rdfs uint64
......@@ -157,6 +164,9 @@ type Counter struct {
Elapsed time.Duration
}
// A Dgraph is the data structure held by the user program for all
// interactions with the Dgraph server. After making grpc
// connection a new Dgraph is created by function NewDgraphClient.
type Dgraph struct {
opts BatchMutationOptions
......@@ -176,6 +186,11 @@ type Dgraph struct {
start time.Time
}
// NewDgraphClient creates a new Dgraph for interacting with
// the Dgraph store connected to in conns. The Dgraph
// client stores blanknode to uid, and XIDnode to uid
// mappings on disk in clientDir.
func NewDgraphClient(conns []*grpc.ClientConn, opts BatchMutationOptions, clientDir string) *Dgraph {
var clients []protos.DgraphClient
for _, conn := range conns {
......@@ -353,6 +368,13 @@ LOOP:
d.wg.Done()
}
// BatchSet adds Edge e as a set to the current batch mutation. Once added,
// the client will apply the mutation to the Dgraph server when it is ready
// to flush its buffers. The edge will be added to one of the batches as
// specified in d's BatchMutationOptions. If that batch fills, it eventually
// flushes. But there is no guarantee of delivery before BatchFlush() is
// called.
func (d *Dgraph) BatchSet(e Edge) error {
d.nquads <- nquadOp{
e: e,
......@@ -362,6 +384,13 @@ func (d *Dgraph) BatchSet(e Edge) error {
return nil
}
// BatchDelete adds Edge e as a delete to the current batch mutation. Once added,
// the client will apply the mutation to the dgraph server when it is ready
// to flush its buffers. The edge will be added to one of the batches as
// specified in d's BatchMutationOptions. If that batch fills, it eventually
// flushes. But there is no guarantee of delivery before BatchFlush() is
// called.
func (d *Dgraph) BatchDelete(e Edge) error {
d.nquads <- nquadOp{
e: e,
......@@ -371,6 +400,12 @@ func (d *Dgraph) BatchDelete(e Edge) error {
return nil
}
// AddSchema adds the given schema mutatation to the batch of schema mutations.
// If the schema mutation applies an index to a UID edge, or if it adds
// reverse to a scalar edge, then the mutation is not added to the batch and an
// error is returned. Once added, the client will apply the schema mutation when
// it is ready to flush its buffers.
func (d *Dgraph) AddSchema(s protos.SchemaUpdate) error {
if err := checkSchema(s); err != nil {
return err
......@@ -379,8 +414,10 @@ func (d *Dgraph) AddSchema(s protos.SchemaUpdate) error {
return nil
}
// Flush waits for all pending requests to complete. It should always be called
// after adding all the NQuads using batch.AddMutation().
// BatchFlush waits for all pending requests to complete. It should always be called
// after all BatchSet and BatchDeletes have been called. Calling BatchFlush
// ends the client session and will cause a panic if further AddSchema,
// BatchSet or BatchDelete functions are called.
func (d *Dgraph) BatchFlush() {
close(d.nquads)
close(d.schema)
......@@ -390,6 +427,9 @@ func (d *Dgraph) BatchFlush() {
}
}
// Run runs the request in req and returns with the completed response from
// the server. Calling Run has no effect on batched mutations.
func (d *Dgraph) Run(ctx context.Context, req *Req) (*protos.Response, error) {
return d.dc[rand.Intn(len(d.dc))].Run(ctx, &req.gr)
}
......@@ -403,6 +443,10 @@ func (d *Dgraph) Counter() Counter {
}
}
// CheckVersion checks if the version of dgraph and dgraphloader are the same.
// If either the versions don't match or the version information could not be
// obtained an error message is printed.
func (d *Dgraph) CheckVersion(ctx context.Context) {
v, err := d.dc[rand.Intn(len(d.dc))].CheckVersion(ctx, &protos.Check{})
if err != nil {
......@@ -418,10 +462,19 @@ You can get the latest version from https://docs.dgraph.io
}
}
// NodeUid creates a Node from the given uint64.
func (d *Dgraph) NodeUid(uid uint64) Node {
return Node{uid: uid}
}
// NodeBlank creates or returns a Node given a string name for the blank node.
// Blank nodes do not exist as labelled nodes in dgraph. Blank nodes are used
// as labels client side for loading and linking nodes correctly. If the
// label is new in this session a new UID is allocated and assigned to the
// label. If the label has already been assigned, the corresponding Node
// is returned.
func (d *Dgraph) NodeBlank(varname string) (Node, error) {
if len(varname) == 0 {
d.alloc.Lock()
......@@ -439,6 +492,13 @@ func (d *Dgraph) NodeBlank(varname string) (Node, error) {
return Node{uid: uid}, nil
}
// NodeXid creates or returns a Node given a string name for an XID node.
// An XID node identifies a node with an edge _xid_, as in
// node --- _xid_ ---> XID string
// See https://docs.dgraph.io/query-language/#external-ids
// If the XID has already been allocated in this client session
// the allocated UID is returned, otherwise a new UID is allocated
// for xid and returned.
func (d *Dgraph) NodeXid(xid string, storeXid bool) (Node, error) {
if len(xid) == 0 {
return Node{}, ErrEmptyXid
......@@ -456,6 +516,17 @@ func (d *Dgraph) NodeXid(xid string, storeXid bool) (Node, error) {
return n, nil
}
// NodeUidVar creates a Node from a variable name. When building a request,
// set and delete mutations may depend on the request's query, as in:
// https://docs.dgraph.io/query-language/#variables-in-mutations
// Such query variables in mutations could be built into the raw query string,
// but it is often more convenient to use client functions than manipulate
// strings.
//
// A request with a query and mutations (including variables in mutations)
// will run in the same manner as if the query and mutations were set into
// the query string.
func (d *Dgraph) NodeUidVar(name string) (Node, error) {
if len(name) == 0 {
return Node{}, ErrEmptyVar
......
......@@ -210,10 +210,22 @@ func fieldMap(typ reflect.Type) map[string]reflect.StructField {
return fmap
}
// Unmarshal is used to convert the query response to a custom struct.
// Response has 4 fields, L(Latency), Schema, AssignedUids and N(Nodes).
// This function takes in the nodes part of the response and tries to
// unmarshal it into the given struct.
// Unmarshal is used to unpack a query response into a custom struct. The
// response from Dgraph.Run (a *protos.Response) has 4 fields, L(Latency),
// Schema, AssignedUids and N(Nodes). This function takes in the nodes part of
// the response and tries to unmarshal it into the given struct v.
//
// protos.Response.N is a slice of Nodes, one for each named query block in the
// request. Each node in that slice has attribute "_root_" and a child for
// each node returned as a result by that query block. For a response resp,
// and struct variable v, with a field tagged with the same name as a query
// block:
// Unmarshal(resp.N, s)
// will try to match named query blocks with tags in s and then unmarshall the
// the matched block into the matched fields of s.
//
// Unmarshal does have to be called at resp.N. Clients can navigate to a
// particular part of the response and unmarshal the children.
func Unmarshal(n []*protos.Node, v interface{}) error {
rv := reflect.ValueOf(v)
if rv.Kind() != reflect.Ptr || rv.IsNil() {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment