Update storage to new object format
This commit is contained in:
57
storage/operator/filter.go
Normal file
57
storage/operator/filter.go
Normal file
@@ -0,0 +1,57 @@
|
||||
package operator
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
)
|
||||
|
||||
type FilterIn struct {
|
||||
Key string
|
||||
Values []interface{}
|
||||
}
|
||||
|
||||
func NewFilterIn(key string, values interface{}) FilterIn {
|
||||
fi := FilterIn{Key: key}
|
||||
switch values.(type) {
|
||||
case []interface{}:
|
||||
fi.Values = values.([]interface{})
|
||||
if len(fi.Values) == 0 {
|
||||
return NewFilterIn(key, nil)
|
||||
}
|
||||
case []string:
|
||||
value := values.([]string)
|
||||
fi.Values = make([]interface{}, len(value))
|
||||
for i := range value {
|
||||
fi.Values[i] = value[i]
|
||||
}
|
||||
if len(fi.Values) == 0 {
|
||||
return NewFilterIn(key, nil)
|
||||
}
|
||||
case []int:
|
||||
value := values.([]int)
|
||||
fi.Values = make([]interface{}, len(value))
|
||||
for i := range value {
|
||||
fi.Values[i] = value[i]
|
||||
}
|
||||
if len(fi.Values) == 0 {
|
||||
return NewFilterIn(key, nil)
|
||||
}
|
||||
case nil:
|
||||
fi.Key = ""
|
||||
default:
|
||||
panic(fmt.Sprintf("cannot convert values to filter in: %T", values))
|
||||
}
|
||||
return fi
|
||||
}
|
||||
|
||||
func (fi FilterIn) MarshalBSON() ([]byte, error) {
|
||||
if len(fi.Key) == 0 {
|
||||
return bson.Marshal(map[string]interface{}{})
|
||||
}
|
||||
return bson.Marshal(map[string]map[string][]interface{}{
|
||||
fi.Key: map[string][]interface{}{
|
||||
"$in": fi.Values,
|
||||
},
|
||||
})
|
||||
}
|
||||
40
storage/operator/filter_test.go
Normal file
40
storage/operator/filter_test.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package operator
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestFilterIn(t *testing.T) {
|
||||
cases := map[string]struct {
|
||||
input interface{}
|
||||
output interface{}
|
||||
}{
|
||||
"[]int{5} => []interface{5}": {
|
||||
input: []int{5},
|
||||
output: []interface{}{5},
|
||||
},
|
||||
"[]string{} => nil": {
|
||||
input: []string{},
|
||||
output: []interface{}{},
|
||||
},
|
||||
"[]interface{}{} => nil": {
|
||||
input: []interface{}{},
|
||||
output: []interface{}{},
|
||||
},
|
||||
"[]interface{}{string} => []interface{string}": {
|
||||
input: []interface{}{"hi"},
|
||||
output: []interface{}{"hi"},
|
||||
},
|
||||
}
|
||||
|
||||
for name, d := range cases {
|
||||
c := d
|
||||
t.Run(name, func(t *testing.T) {
|
||||
filterIn := fmt.Sprint(NewFilterIn("key", c.input).Values)
|
||||
if want := fmt.Sprint(c.output); want != filterIn {
|
||||
t.Error(want, filterIn)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
59
storage/operator/modify.go
Normal file
59
storage/operator/modify.go
Normal file
@@ -0,0 +1,59 @@
|
||||
package operator
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
)
|
||||
|
||||
type Unset string
|
||||
|
||||
func (u Unset) MarshalBSON() ([]byte, error) {
|
||||
return opMarshal("$unset", string(u), "")
|
||||
}
|
||||
|
||||
type PopIf struct {
|
||||
Key string
|
||||
Filter interface{}
|
||||
}
|
||||
|
||||
func (pi PopIf) MarshalBSON() ([]byte, error) {
|
||||
return opMarshal("$pull", pi.Key, pi.Filter)
|
||||
}
|
||||
|
||||
type Set struct {
|
||||
Key string
|
||||
Value interface{}
|
||||
}
|
||||
|
||||
func (s Set) MarshalBSON() ([]byte, error) {
|
||||
return opMarshal("$set", s.Key, s.Value)
|
||||
}
|
||||
|
||||
type Push struct {
|
||||
Key string
|
||||
Value interface{}
|
||||
}
|
||||
|
||||
func (p Push) MarshalBSON() ([]byte, error) {
|
||||
return opMarshal("$push", p.Key, p.Value)
|
||||
}
|
||||
|
||||
func opMarshal(op, key string, value interface{}) ([]byte, error) {
|
||||
marshalable := opMarshalable(op, key, value)
|
||||
if len(marshalable) == 0 {
|
||||
return nil, fmt.Errorf("failed marshalling op")
|
||||
}
|
||||
return bson.Marshal(marshalable)
|
||||
}
|
||||
|
||||
func opMarshalable(op, key string, value interface{}) map[string]map[string]interface{} {
|
||||
if len(key) == 0 {
|
||||
return nil
|
||||
}
|
||||
return map[string]map[string]interface{}{
|
||||
op: map[string]interface{}{
|
||||
key: value,
|
||||
},
|
||||
}
|
||||
}
|
||||
65
storage/operator/modify_test.go
Normal file
65
storage/operator/modify_test.go
Normal file
@@ -0,0 +1,65 @@
|
||||
package operator
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
)
|
||||
|
||||
func TestModify(t *testing.T) {
|
||||
cases := map[string]struct {
|
||||
marshalme interface{}
|
||||
key1 string
|
||||
key2 string
|
||||
want interface{}
|
||||
}{
|
||||
"unset": {
|
||||
marshalme: Unset("field"),
|
||||
key1: "field",
|
||||
key2: "$unset",
|
||||
want: nil,
|
||||
},
|
||||
"popif": {
|
||||
marshalme: PopIf{Key: "field", Filter: "world"},
|
||||
key1: "$pull",
|
||||
key2: "field",
|
||||
want: "world",
|
||||
},
|
||||
"popif map": {
|
||||
marshalme: PopIf{Key: "field", Filter: map[string]string{"world": "jk"}},
|
||||
key1: "$pull",
|
||||
key2: "field",
|
||||
want: map[string]string{"world": "jk"},
|
||||
},
|
||||
"set": {
|
||||
marshalme: Set{Key: "field", Value: "value"},
|
||||
key1: "$set",
|
||||
key2: "field",
|
||||
want: "value",
|
||||
},
|
||||
"push": {
|
||||
marshalme: Push{Key: "field", Value: "value"},
|
||||
key1: "$push",
|
||||
key2: "field",
|
||||
want: "value",
|
||||
},
|
||||
}
|
||||
|
||||
for name, d := range cases {
|
||||
c := d
|
||||
t.Run(name, func(t *testing.T) {
|
||||
var v map[string]map[string]interface{}
|
||||
if b, err := bson.Marshal(c.marshalme); err != nil {
|
||||
t.Error(err)
|
||||
} else if err := bson.Unmarshal(b, &v); err != nil {
|
||||
t.Error(err)
|
||||
} else if got := v[c.key1][c.key2]; fmt.Sprint(got) != fmt.Sprint(c.want) {
|
||||
a, _ := json.Marshal(got)
|
||||
b, _ := json.Marshal(v)
|
||||
t.Errorf("want [%s][%s] = %v, got %s from %s", c.key1, c.key2, c.want, string(a), string(b))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user