Skip to content

Commit 9dc739d

Browse files
committed
Adding Edge functions
1 parent afeb0af commit 9dc739d

File tree

5 files changed

+200
-8
lines changed

5 files changed

+200
-8
lines changed

connection.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ type Request interface {
4747
SetQuery(key, value string) Request
4848
// SetBody sets the content of the request.
4949
// The protocol of the connection determines what kinds of marshalling is taking place.
50-
SetBody(body interface{}) (Request, error)
50+
// When multiple bodies are given, they are merged, with fields in the first document prevailing.
51+
SetBody(body ...interface{}) (Request, error)
5152
// SetBodyArray sets the content of the request as an array.
5253
// If the given mergeArray is not nil, its elements are merged with the elements in the body array (mergeArray data overrides bodyArray data).
5354
// The merge is NOT recursive.

edge_collection.go

+23
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,25 @@ type EdgeCollection interface {
2929
// Name returns the name of the collection.
3030
Name() string
3131

32+
// ReadEdge reads a single edge with given key from this edge collection.
33+
// The document data is stored into result, the document meta data is returned.
34+
// If no document exists with given key, a NotFoundError is returned.
35+
ReadEdge(ctx context.Context, key string, result interface{}) (EdgeMeta, error)
36+
3237
// CreateEdge creates a new edge in this edge collection.
3338
CreateEdge(ctx context.Context, from, to DocumentID, document interface{}) (DocumentMeta, error)
3439

40+
// UpdateEdge updates a single edge with given key in the collection.
41+
// To & from are allowed to be empty. If they are empty, they are not updated.
42+
// The document meta data is returned.
43+
// If no document exists with given key, a NotFoundError is returned.
44+
UpdateEdge(ctx context.Context, key string, from, to DocumentID, update interface{}) (DocumentMeta, error)
45+
46+
// ReplaceEdge replaces a single edge with given key in the collection.
47+
// The document meta data is returned.
48+
// If no document exists with given key, a NotFoundError is returned.
49+
ReplaceEdge(ctx context.Context, key string, from, to DocumentID, document interface{}) (DocumentMeta, error)
50+
3551
// Remove the edge collection from the graph.
3652
Remove(ctx context.Context) error
3753

@@ -40,3 +56,10 @@ type EdgeCollection interface {
4056
// to: contains the names of one or more edge collections that can contain target vertices.
4157
Replace(ctx context.Context, from, to []string) error
4258
}
59+
60+
// EdgeMeta is DocumentMeta data extended with From & To fields.
61+
type EdgeMeta struct {
62+
DocumentMeta
63+
From DocumentID `json:"_from,omitempty"`
64+
To DocumentID `json:"_to,omitempty"`
65+
}

edge_collection_impl.go

+136-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ package driver
2424

2525
import (
2626
"context"
27+
"fmt"
2728
"path"
2829
)
2930

@@ -48,6 +49,11 @@ type edgeCollection struct {
4849
conn Connection
4950
}
5051

52+
type edgeDocument struct {
53+
From DocumentID `json:"_from,omitempty"`
54+
To DocumentID `json:"_to,omitempty"`
55+
}
56+
5157
// relPath creates the relative path to this edge collection (`_db/<db-name>/_api/gharial/<graph-name>/edge/<collection-name>`)
5258
func (c *edgeCollection) relPath() string {
5359
escapedName := pathEscape(c.name)
@@ -59,9 +65,138 @@ func (c *edgeCollection) Name() string {
5965
return c.name
6066
}
6167

68+
// ReadEdge reads a single edge with given key from this edge collection.
69+
// The document data is stored into result, the document meta data is returned.
70+
// If no document exists with given key, a NotFoundError is returned.
71+
func (c *edgeCollection) ReadEdge(ctx context.Context, key string, result interface{}) (EdgeMeta, error) {
72+
if err := validateKey(key); err != nil {
73+
return EdgeMeta{}, WithStack(err)
74+
}
75+
escapedKey := pathEscape(key)
76+
req, err := c.conn.NewRequest("GET", path.Join(c.relPath(), escapedKey))
77+
if err != nil {
78+
return EdgeMeta{}, WithStack(err)
79+
}
80+
applyContextSettings(ctx, req)
81+
resp, err := c.conn.Do(ctx, req)
82+
if err != nil {
83+
return EdgeMeta{}, WithStack(err)
84+
}
85+
if err := resp.CheckStatus(200); err != nil {
86+
return EdgeMeta{}, WithStack(err)
87+
}
88+
// Parse metadata
89+
var meta EdgeMeta
90+
if err := resp.ParseBody("edge", &meta); err != nil {
91+
return EdgeMeta{}, WithStack(err)
92+
}
93+
return meta, nil
94+
}
95+
6296
// CreateEdge creates a new edge in this edge collection.
6397
func (c *edgeCollection) CreateEdge(ctx context.Context, from, to DocumentID, document interface{}) (DocumentMeta, error) {
64-
return DocumentMeta{}, nil
98+
if err := from.Validate(); err != nil {
99+
return DocumentMeta{}, WithStack(InvalidArgumentError{Message: fmt.Sprintf("from invalid: %v", err)})
100+
}
101+
if err := to.Validate(); err != nil {
102+
return DocumentMeta{}, WithStack(InvalidArgumentError{Message: fmt.Sprintf("to invalid: %v", err)})
103+
}
104+
req, err := c.conn.NewRequest("POST", c.relPath())
105+
if err != nil {
106+
return DocumentMeta{}, WithStack(err)
107+
}
108+
if _, err := req.SetBody(edgeDocument{To: to, From: from}, document); err != nil {
109+
return DocumentMeta{}, WithStack(err)
110+
}
111+
applyContextSettings(ctx, req)
112+
resp, err := c.conn.Do(ctx, req)
113+
if err != nil {
114+
return DocumentMeta{}, WithStack(err)
115+
}
116+
if err := resp.CheckStatus(201, 202); err != nil {
117+
return DocumentMeta{}, WithStack(err)
118+
}
119+
// Parse metadata
120+
var meta DocumentMeta
121+
if err := resp.ParseBody("edge", &meta); err != nil {
122+
return DocumentMeta{}, WithStack(err)
123+
}
124+
return meta, nil
125+
}
126+
127+
// UpdateEdge updates a single edge with given key in the collection.
128+
// To & from are allowed to be empty. If they are empty, they are not updated.
129+
// The document meta data is returned.
130+
// If no document exists with given key, a NotFoundError is returned.
131+
func (c *edgeCollection) UpdateEdge(ctx context.Context, key string, from, to DocumentID, update interface{}) (DocumentMeta, error) {
132+
if err := from.ValidateOrEmpty(); err != nil {
133+
return DocumentMeta{}, WithStack(InvalidArgumentError{Message: fmt.Sprintf("from invalid: %v", err)})
134+
}
135+
if err := to.ValidateOrEmpty(); err != nil {
136+
return DocumentMeta{}, WithStack(InvalidArgumentError{Message: fmt.Sprintf("to invalid: %v", err)})
137+
}
138+
var edgeDoc *edgeDocument
139+
if !from.IsEmpty() || !to.IsEmpty() {
140+
edgeDoc = &edgeDocument{
141+
From: from,
142+
To: to,
143+
}
144+
}
145+
req, err := c.conn.NewRequest("PATCH", c.relPath())
146+
if err != nil {
147+
return DocumentMeta{}, WithStack(err)
148+
}
149+
if _, err := req.SetBody(edgeDoc, update); err != nil {
150+
return DocumentMeta{}, WithStack(err)
151+
}
152+
applyContextSettings(ctx, req)
153+
resp, err := c.conn.Do(ctx, req)
154+
if err != nil {
155+
return DocumentMeta{}, WithStack(err)
156+
}
157+
if err := resp.CheckStatus(200, 202); err != nil {
158+
return DocumentMeta{}, WithStack(err)
159+
}
160+
// Parse metadata
161+
var meta DocumentMeta
162+
if err := resp.ParseBody("edge", &meta); err != nil {
163+
return DocumentMeta{}, WithStack(err)
164+
}
165+
return meta, nil
166+
}
167+
168+
func (c *edgeCollection) ReplaceEdge(ctx context.Context, key string, from, to DocumentID, update interface{}) (DocumentMeta, error) {
169+
if err := from.Validate(); err != nil {
170+
return DocumentMeta{}, WithStack(InvalidArgumentError{Message: fmt.Sprintf("from invalid: %v", err)})
171+
}
172+
if err := to.Validate(); err != nil {
173+
return DocumentMeta{}, WithStack(InvalidArgumentError{Message: fmt.Sprintf("to invalid: %v", err)})
174+
}
175+
edgeDoc := edgeDocument{
176+
From: from,
177+
To: to,
178+
}
179+
req, err := c.conn.NewRequest("PUT", c.relPath())
180+
if err != nil {
181+
return DocumentMeta{}, WithStack(err)
182+
}
183+
if _, err := req.SetBody(edgeDoc, update); err != nil {
184+
return DocumentMeta{}, WithStack(err)
185+
}
186+
applyContextSettings(ctx, req)
187+
resp, err := c.conn.Do(ctx, req)
188+
if err != nil {
189+
return DocumentMeta{}, WithStack(err)
190+
}
191+
if err := resp.CheckStatus(201, 202); err != nil {
192+
return DocumentMeta{}, WithStack(err)
193+
}
194+
// Parse metadata
195+
var meta DocumentMeta
196+
if err := resp.ParseBody("edge", &meta); err != nil {
197+
return DocumentMeta{}, WithStack(err)
198+
}
199+
return meta, nil
65200
}
66201

67202
// Remove the edge collection from the graph.

http/request.go

+22-6
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,29 @@ func (r *httpRequest) SetQuery(key, value string) driver.Request {
5757

5858
// SetBody sets the content of the request.
5959
// The protocol of the connection determines what kinds of marshalling is taking place.
60-
func (r *httpRequest) SetBody(body interface{}) (driver.Request, error) {
61-
if data, err := json.Marshal(body); err != nil {
62-
return r, driver.WithStack(err)
63-
} else {
64-
r.body = data
60+
func (r *httpRequest) SetBody(body ...interface{}) (driver.Request, error) {
61+
switch len(body) {
62+
case 0:
63+
return r, driver.WithStack(fmt.Errorf("Must provide at least 1 body"))
64+
case 1:
65+
if data, err := json.Marshal(body[0]); err != nil {
66+
return r, driver.WithStack(err)
67+
} else {
68+
r.body = data
69+
}
70+
return r, nil
71+
case 2:
72+
mo := mergeObject{Object: body[1], Merge: body[0]}
73+
if data, err := json.Marshal(mo); err != nil {
74+
return r, driver.WithStack(err)
75+
} else {
76+
r.body = data
77+
}
78+
return r, nil
79+
default:
80+
return r, driver.WithStack(fmt.Errorf("Must provide at most 2 bodies"))
6581
}
66-
return r, nil
82+
6783
}
6884

6985
// SetBodyArray sets the content of the request as an array.

id.go

+17
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,23 @@ func (id DocumentID) Validate() error {
4949
return nil
5050
}
5151

52+
// ValidateOrEmpty validates the given id unless it is empty.
53+
// In case of empty, nil is returned.
54+
func (id DocumentID) ValidateOrEmpty() error {
55+
if id == "" {
56+
return nil
57+
}
58+
if err := id.Validate(); err != nil {
59+
return WithStack(err)
60+
}
61+
return nil
62+
}
63+
64+
// IsEmpty returns true if the given ID is empty, false otherwise.
65+
func (id DocumentID) IsEmpty() bool {
66+
return id == ""
67+
}
68+
5269
// Collection returns the collection part of the ID.
5370
func (id DocumentID) Collection() string {
5471
parts := strings.Split(string(id), "/")

0 commit comments

Comments
 (0)