diff --git a/storage/entity/one.go b/storage/entity/one.go index 01e581b..a6ed574 100644 --- a/storage/entity/one.go +++ b/storage/entity/one.go @@ -6,7 +6,6 @@ import ( "time" "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/primitive" ) const ( @@ -22,14 +21,14 @@ const ( ) type One struct { - Name string `bson:"_id,omitempty" json:"name,omitempty"` - Type string `bson:"type,omitempty" json:"type,omitempty"` - Title string `bson:"title,omitempty" json:"title,omitempty"` - Image string `bson:"image,omitempty" json:"image,omitempty"` - Text string `bson:"text,omitempty" json:"text,omitempty"` - Relationship string `bson:"relationship,omitempty" json:"relationship,omitempty"` - Modified int64 `bson:"modified,omitempty" json:"modified,omitempty"` - Connections []One `bson:"connections,omitempty" json:"connections,omitempty"` + Name string `bson:"_id,omitempty" json:"name,omitempty"` + Type string `bson:"type,omitempty" json:"type,omitempty"` + Title string `bson:"title,omitempty" json:"title,omitempty"` + Image string `bson:"image,omitempty" json:"image,omitempty"` + Text string `bson:"text,omitempty" json:"text,omitempty"` + Relationship string `bson:"relationship,omitempty" json:"relationship,omitempty"` + Modified int64 `bson:"modified,omitempty" json:"modified,omitempty"` + Connections map[string]One `bson:"connections,omitempty" json:"connections,omitempty"` } func (o One) Query() One { @@ -38,14 +37,17 @@ func (o One) Query() One { func (o One) Peers() []string { names := make([]string, len(o.Connections)) - for i := range o.Connections { - names[i] = o.Connections[i].Name + i := 0 + for k := range o.Connections { + names[i] = o.Connections[k].Name + i += 1 } return names } func (o One) MarshalBSON() ([]byte, error) { - if fmt.Sprint(o) != fmt.Sprint(o.Query()) { + isMin := fmt.Sprint(o) == fmt.Sprint(o.Query()) + if !isMin { o.Modified = time.Now().UnixNano() } b, err := json.Marshal(o) @@ -60,32 +62,27 @@ func (o One) MarshalBSON() ([]byte, error) { m[Name] = name delete(m, JSONName) } - var connections primitive.A - switch m[Connections].(type) { - case nil: - case []interface{}: - connections = primitive.A(m[Connections].([]interface{})) - case primitive.A: - connections = m[Connections].(primitive.A) - default: - return nil, fmt.Errorf("bad type for %q: %T", Connections, m[Connections]) - } - curL := len(connections) - wantL := len(o.Connections) - for i := curL; i < wantL; i++ { - connections = append(connections, nil) - } - for i, connection := range o.Connections { - b, err := bson.Marshal(connection) - if err != nil { - return nil, err + if !isMin { + connections := map[string]interface{}{} + switch m[Connections].(type) { + case nil: + case map[string]interface{}: + connections = m[Connections].(map[string]interface{}) + default: + return nil, fmt.Errorf("bad connections type %T", m[Connections]) } - m := bson.M{} - if err := bson.Unmarshal(b, &m); err != nil { - return nil, err + for k := range connections { + b, err := bson.Marshal(o.Connections[k]) + if err != nil { + return nil, err + } + m := bson.M{} + if err := bson.Unmarshal(b, &m); err != nil { + return nil, err + } + connections[k] = m } - connections[i] = m + m[Connections] = connections } - m[Connections] = connections return bson.Marshal(m) } diff --git a/storage/entity/one_test.go b/storage/entity/one_test.go index 5aefbed..667f9d7 100644 --- a/storage/entity/one_test.go +++ b/storage/entity/one_test.go @@ -31,7 +31,7 @@ func TestOneMarshalBSON(t *testing.T) { one: (One{Name: "hello", Type: "world", Modified: 1}), }, "w/ connections": { - one: (One{Name: "hello", Type: "world", Modified: 1, Connections: []One{One{Name: "hi", Relationship: "mom"}}}), + one: (One{Name: "hello", Type: "world", Modified: 1, Connections: map[string]One{"hi": One{Name: "hi", Relationship: "mom"}}}), }, } @@ -56,8 +56,10 @@ func TestOneMarshalBSON(t *testing.T) { } c.one.Modified = 0 one.Modified = 0 - for i := range one.Connections { - one.Connections[i].Modified = 0 + for k := range one.Connections { + temp := one.Connections[k] + temp.Modified = 0 + one.Connections[k] = temp } if fmt.Sprint(c.one) != fmt.Sprint(one) { t.Error(c.one, one) diff --git a/storage/graph_test.go b/storage/graph_test.go index c6ca855..95fed95 100644 --- a/storage/graph_test.go +++ b/storage/graph_test.go @@ -2,6 +2,7 @@ package storage import ( "context" + "fmt" "local/dndex/storage/entity" "local/dndex/storage/operator" "os" @@ -34,7 +35,7 @@ func TestIntegration(t *testing.T) { randomOne(), randomOne(), } - ones[0].Connections = []entity.One{entity.One{Name: ones[2].Name, Relationship: ":("}} + ones[0].Connections = map[string]entity.One{ones[2].Name: entity.One{Name: ones[2].Name, Relationship: ":("}} t.Run("graph.Insert(...)", func(t *testing.T) { for _, one := range ones { @@ -68,7 +69,7 @@ func TestIntegration(t *testing.T) { }) t.Run("graph.Update(foo, --bar)", func(t *testing.T) { - err := graph.Update(ctx, ones[0].Query(), operator.Set{entity.Connections, []interface{}{}}) + err := graph.Update(ctx, ones[0].Query(), operator.Set{entity.Connections, map[string]interface{}{}}) if err != nil { t.Fatal(err) } @@ -90,8 +91,11 @@ func TestIntegration(t *testing.T) { } }) - t.Run("graph.Update(foo, ++...); graph.Update(foo, --if :()", func(t *testing.T) { - err := graph.Update(ctx, ones[0].Query(), operator.Set{entity.Connections, []entity.One{entity.One{Name: "hello", Relationship: ":("}}}) + t.Run("graph.Update(foo, +=2); graph.Update(foo, -=1)", func(t *testing.T) { + err := graph.Update(ctx, ones[0].Query(), operator.Set{entity.Connections, map[string]entity.One{ + "hello": entity.One{Name: "hello", Relationship: ":("}, + "world": entity.One{Name: "world", Relationship: ":("}, + }}) if err != nil { t.Fatal(err) } @@ -104,29 +108,24 @@ func TestIntegration(t *testing.T) { if len(some1) != 1 { t.Fatal(len(some1)) } - if len(some1[0].Peers()) != 1 { + if len(some1[0].Peers()) != 2 { t.Fatal(some1[0].Peers()) } - err = graph.Update(ctx, ones[0].Query(), operator.PopIf{entity.Connections, map[string]string{entity.Relationship: ":("}}) + err = graph.Update(ctx, ones[0].Query(), operator.Unset(fmt.Sprintf("%s.world", entity.Connections))) if err != nil { t.Fatal(err) } - some2, err := graph.List(ctx, ones[0].Name) if err != nil { t.Fatal(err) } t.Logf("sm2 = %+v", some2[0]) - - if len(some1) != len(some2) { + if len(some2) != 1 { t.Fatal(len(some2)) } - if len(some1[0].Connections) == len(some2[0].Connections) { - t.Fatal(len(some2[0].Connections)) - } - if len(some2[0].Connections) == len(ones) { - t.Fatal(len(some2[0].Connections)) + if len(some2[0].Peers()) != 1 { + t.Fatal(some2[0].Peers()) } }) } @@ -139,6 +138,6 @@ func randomOne() entity.One { Image: "/path/to.jpg", Text: "tee hee xd", Modified: time.Now().UnixNano(), - Connections: []entity.One{}, + Connections: map[string]entity.One{}, } } diff --git a/view/html_test.go b/view/html_test.go index 7dfc68c..e53e76a 100644 --- a/view/html_test.go +++ b/view/html_test.go @@ -94,10 +94,10 @@ func fillDB(t *testing.T, g storage.Graph) []entity.One { for i := range ones { ones[i] = randomOne() if i > 0 { - ones[i].Connections = []entity.One{entity.One{ + ones[i].Connections[ones[i-1].Name] = entity.One{ Name: ones[i-1].Name, Relationship: ":D", - }} + } } } for i := range ones { @@ -110,8 +110,12 @@ func fillDB(t *testing.T, g storage.Graph) []entity.One { t.Fatal(len(results)) } else if len(results[0].Connections) != len(ones[i].Connections) { t.Fatal(len(results[0].Connections), len(ones[i].Connections)) - } else if len(results[0].Connections) > 0 && len(results[0].Connections[0].Name) == 0 { - t.Fatalf("name is gone: %+v", results) + } else if len(results[0].Connections) > 0 { + for k, v := range results[0].Connections { + if k == "" || v.Name == "" { + t.Fatalf("name is gone: %q:%+v", k, v) + } + } } } return ones @@ -125,6 +129,6 @@ func randomOne() entity.One { Image: "imge-" + uuid.New().String()[:5], Text: "text-" + uuid.New().String()[:5], Modified: time.Now().UnixNano(), - Connections: []entity.One{}, + Connections: map[string]entity.One{}, } }