Skip to content

Commit

Permalink
Merge pull request RedisGraph#13 from RedisGraph/array_support
Browse files Browse the repository at this point in the history
added array support
  • Loading branch information
swilly22 authored Sep 5, 2019
2 parents 0d66f2d + a325fb3 commit eb62d44
Show file tree
Hide file tree
Showing 6 changed files with 333 additions and 210 deletions.
105 changes: 93 additions & 12 deletions client_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package redisgraph

import (
"testing"
"os"
"github.com/stretchr/testify/assert"
"testing"

"github.com/gomodule/redigo/redis"
"github.com/stretchr/testify/assert"
)

var graph Graph
Expand All @@ -24,7 +25,7 @@ func createGraph() {
john.SetProperty("age", 33)
john.SetProperty("gender", "male")
john.SetProperty("status", "single")

japan.SetProperty("name", "Japan")
japan.SetProperty("population", 126800000)

Expand All @@ -51,10 +52,10 @@ func shutdown() {
}

func TestMain(m *testing.M) {
setup()
code := m.Run()
shutdown()
os.Exit(code)
setup()
code := m.Run()
shutdown()
os.Exit(code)
}

func TestMatchQuery(t *testing.T) {
Expand All @@ -63,7 +64,7 @@ func TestMatchQuery(t *testing.T) {
if err != nil {
t.Error(err)
}

assert.Equal(t, len(res.results), 1, "expecting 1 result record")

s, ok := (res.results[0][0]).(*Node)
Expand All @@ -83,7 +84,7 @@ func TestMatchQuery(t *testing.T) {
assert.Equal(t, s.GetProperty("age"), 33, "Unexpected property value.")
assert.Equal(t, s.GetProperty("gender"), "male", "Unexpected property value.")
assert.Equal(t, s.GetProperty("status"), "single", "Unexpected property value.")

assert.Equal(t, e.GetProperty("year"), 2017, "Unexpected property value.")

assert.Equal(t, d.GetProperty("name"), "Japan", "Unexpected property value.")
Expand All @@ -96,9 +97,9 @@ func TestCreateQuery(t *testing.T) {
if err != nil {
t.Error(err)
}

assert.True(t, res.Empty(), "Expecting empty result-set")

// Validate statistics.
assert.Equal(t, res.NodesCreated(), 1, "Expecting a single node to be created.")
assert.Equal(t, res.PropertiesSet(), 1, "Expecting a songle property to be added.")
Expand All @@ -108,8 +109,88 @@ func TestCreateQuery(t *testing.T) {
if err != nil {
t.Error(err)
}

assert.False(t, res.Empty(), "Expecting resultset to include a single node.")
w := (res.results[0][0]).(*Node)
assert.Equal(t, w.Label, "WorkPlace", "Unexpected node label.")
}

func TestArray(t *testing.T) {

graph.Flush()
graph.Query("MATCH (n) DELETE n")

q := "CREATE (:person{name:'a',age:32,array:[0,1,2]})"
res, err := graph.Query(q)
if err != nil {
t.Error(err)
}

q = "CREATE (:person{name:'b',age:30,array:[3,4,5]})"
res, err = graph.Query(q)
if err != nil {
t.Error(err)
}

q = "WITH [0,1,2] as x return x"
res, err = graph.Query(q)
if err != nil {
t.Error(err)
}

assert.Equal(t, len(res.results), 1, "expecting 1 result record")

assert.Equal(t, []interface{}{0, 1, 2}, res.results[0][0])

q = "unwind([0,1,2]) as x return x"
res, err = graph.Query(q)
if err != nil {
t.Error(err)
}
assert.Equal(t, len(res.results), 3, "expecting 3 result record")

for i := 0; i < 3; i++ {
assert.Equal(t, i, res.results[i][0])
}

q = "MATCH(n) return collect(n) as x"
res, err = graph.Query(q)
if err != nil {
t.Error(err)
}

a := NodeNew("person", "", nil)
b := NodeNew("person", "", nil)

a.SetProperty("name", "a")
a.SetProperty("age", 32)
a.SetProperty("array", []interface{}{0, 1, 2})

b.SetProperty("name", "b")
b.SetProperty("age", 30)
b.SetProperty("array", []interface{}{3, 4, 5})

assert.Equal(t, 1, len(res.results), "expecting 1 results record")

arr := res.results[0][0].([]interface{})

assert.Equal(t, 2, len(arr))

resA := arr[0].(*Node)
resB := arr[1].(*Node)
// the order of values in the array returned by collect operation is not defined
// check for the node that contains the name "a" and set it to be resA
if resA.GetProperty("name") != "a" {
resA = arr[1].(*Node)
resB = arr[0].(*Node)
}

assert.Equal(t, a.GetProperty("name"), resA.GetProperty("name"), "Unexpected property value.")
assert.Equal(t, a.GetProperty("age"), resA.GetProperty("age"), "Unexpected property value.")
assert.Equal(t, a.GetProperty("array"), resA.GetProperty("array"), "Unexpected property value.")

assert.Equal(t, b.GetProperty("name"), resB.GetProperty("name"), "Unexpected property value.")
assert.Equal(t, b.GetProperty("age"), resB.GetProperty("age"), "Unexpected property value.")
assert.Equal(t, b.GetProperty("array"), resB.GetProperty("array"), "Unexpected property value.")

}
36 changes: 18 additions & 18 deletions edge.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,50 +7,50 @@ import (

// Edge represents an edge connecting two nodes in the graph.
type Edge struct {
ID uint64
ID uint64
Relation string
Source *Node
Destination *Node
Destination *Node
Properties map[string]interface{}
srcNodeID uint64
destNodeID uint64
graph *Graph
srcNodeID uint64
destNodeID uint64
graph *Graph
}

func EdgeNew(relation string, srcNode *Node, destNode *Node, properties map[string]interface{}) *Edge {
p := properties
p := properties
if p == nil {
p = make(map[string]interface{})
}

return &Edge{
Relation: relation,
Source: srcNode,
Destination: destNode,
Properties: p,
graph: nil,
}
return &Edge{
Relation: relation,
Source: srcNode,
Destination: destNode,
Properties: p,
graph: nil,
}
}

func (e *Edge) SetProperty(key string, value interface{}) {
e.Properties[key] = value
}

func (e *Edge) GetProperty(key string) interface{} {
v,_ := e.Properties[key]
v, _ := e.Properties[key]
return v
}

func (e Edge) SourceNodeID() uint64 {
if(e.Source != nil) {
if e.Source != nil {
return e.Source.ID
} else {
return e.srcNodeID
}
}

func (e Edge) DestNodeID() uint64 {
if(e.Source != nil) {
if e.Source != nil {
return e.Destination.ID
} else {
return e.destNodeID
Expand All @@ -64,7 +64,7 @@ func (e Edge) String() string {

p := make([]string, 0, len(e.Properties))
for k, v := range e.Properties {
p = append(p, fmt.Sprintf("%s:%v", k, QuoteString(v)))
p = append(p, fmt.Sprintf("%s:%v", k, ToString(v)))
}

s := fmt.Sprintf("{%s}", strings.Join(p, ","))
Expand All @@ -83,7 +83,7 @@ func (e Edge) Encode() string {
if len(e.Properties) > 0 {
p := make([]string, 0, len(e.Properties))
for k, v := range e.Properties {
p = append(p, fmt.Sprintf("%s:%v", k, QuoteString(v)))
p = append(p, fmt.Sprintf("%s:%v", k, ToString(v)))
}

s = append(s, "{")
Expand Down
80 changes: 40 additions & 40 deletions graph.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,26 @@ import (

// Graph represents a graph, which is a collection of nodes and edges.
type Graph struct {
Id string
Nodes map[string]*Node
Edges []*Edge
Conn redis.Conn
labels []string // List of node labels.
relationshipTypes []string // List of relation types.
properties []string // List of properties.
mutex sync.Mutex // Lock, used for updating internal state.
Id string
Nodes map[string]*Node
Edges []*Edge
Conn redis.Conn
labels []string // List of node labels.
relationshipTypes []string // List of relation types.
properties []string // List of properties.
mutex sync.Mutex // Lock, used for updating internal state.
}

// New creates a new graph.
func GraphNew(Id string, conn redis.Conn) Graph {
g := Graph {
Id: Id,
Nodes: make(map[string]*Node, 0),
Edges: make([]*Edge, 0),
Conn: conn,
labels: make([]string, 0),
g := Graph{
Id: Id,
Nodes: make(map[string]*Node, 0),
Edges: make([]*Edge, 0),
Conn: conn,
labels: make([]string, 0),
relationshipTypes: make([]string, 0),
properties: make([]string, 0),
properties: make([]string, 0),
}
return g
}
Expand Down Expand Up @@ -179,53 +179,53 @@ func (g *Graph) getProperty(propIdx int) string {

// CallProcedure invokes procedure.
func (g *Graph) CallProcedure(procedure string, yield []string, args ...interface{}) (*QueryResult, error) {
q := fmt.Sprintf("CALL %s(", procedure)
tmp := make([]string, 0, len(args))
q := fmt.Sprintf("CALL %s(", procedure)

tmp := make([]string, 0, len(args))
for arg := range args {
tmp = append(tmp, QuoteString(arg).(string))
tmp = append(tmp, ToString(arg).(string))
}
q += fmt.Sprintf("%s)", strings.Join(tmp, ","))

if yield != nil && len(yield) > 0 {
q += fmt.Sprintf(" YIELD %s", strings.Join(yield, ","))
q += fmt.Sprintf(" YIELD %s", strings.Join(yield, ","))
}

return g.Query(q)
return g.Query(q)
}

// Labels, retrieves all node labels.
func (g *Graph) Labels() []string {
qr,_ := g.CallProcedure("db.labels", nil)
l := make([]string, len(qr.results))
qr, _ := g.CallProcedure("db.labels", nil)

l := make([]string, len(qr.results))

for idx, r := range(qr.results) {
l[idx] = r[0].(string)
}
return l
for idx, r := range qr.results {
l[idx] = r[0].(string)
}
return l
}

// RelationshipTypes, retrieves all edge relationship types.
func (g *Graph) RelationshipTypes() []string {
qr,_ := g.CallProcedure("db.relationshipTypes", nil)
qr, _ := g.CallProcedure("db.relationshipTypes", nil)

rt := make([]string, len(qr.results))
rt := make([]string, len(qr.results))

for idx, r := range(qr.results) {
rt[idx] = r[0].(string)
}
return rt
for idx, r := range qr.results {
rt[idx] = r[0].(string)
}
return rt
}

// PropertyKeys, retrieves all properties names.
func (g *Graph) PropertyKeys() []string {
qr,_ := g.CallProcedure("db.propertyKeys", nil)
qr, _ := g.CallProcedure("db.propertyKeys", nil)

p := make([]string, len(qr.results))
p := make([]string, len(qr.results))

for idx, r := range(qr.results) {
p[idx] = r[0].(string)
}
return p
for idx, r := range qr.results {
p[idx] = r[0].(string)
}
return p
}
Loading

0 comments on commit eb62d44

Please sign in to comment.