diff --git a/storage/driver/boltdb.go b/storage/driver/boltdb.go index 23e5dfa..1d1850f 100644 --- a/storage/driver/boltdb.go +++ b/storage/driver/boltdb.go @@ -8,6 +8,7 @@ import ( "local/dndex/storage/entity" "os" "regexp" + "strings" "github.com/boltdb/bolt" "go.mongodb.org/mongo-driver/bson" @@ -262,6 +263,8 @@ func apply(doc bson.M, operator interface{}) (bson.M, error) { switch k { case "$set": op = applySet + case "$unset": + op = applyUnset default: return nil, errors.New("cannot apply operation " + k) } @@ -273,6 +276,38 @@ func apply(doc bson.M, operator interface{}) (bson.M, error) { return doc, nil } +func applyUnset(doc, operator bson.M) (bson.M, error) { + for k := range operator { + if k == entity.Name { + return nil, errModifiedReserved + } + nesting := strings.Split(k, ".") + if len(nesting) > 1 { + mInterface, ok := doc[nesting[0]] + if !ok { + return nil, fmt.Errorf("path does not exist: %s (%s): %+v", k, nesting[0], doc) + } + m, ok := mInterface.(map[string]interface{}) + if !ok { + pm, pmok := mInterface.(primitive.M) + m = map[string]interface{}(pm) + ok = pmok + } + if !ok { + return nil, fmt.Errorf("subpath cannot be followed for non object: %s (%s): %+v (%T)", k, nesting[0], mInterface, mInterface) + } + subdoc, err := applyUnset(bson.M(m), bson.M{strings.Join(nesting[1:], "."): ""}) + if err != nil { + return nil, err + } + operator[k] = subdoc + } else { + delete(doc, k) + } + } + return doc, nil +} + func applySet(doc, operator bson.M) (bson.M, error) { for k, v := range operator { if k == entity.Name { diff --git a/storage/driver/boltdb_test.go b/storage/driver/boltdb_test.go index 1d58b6d..943b58b 100644 --- a/storage/driver/boltdb_test.go +++ b/storage/driver/boltdb_test.go @@ -179,6 +179,10 @@ func TestBoltDBUpdate(t *testing.T) { t.Fatal(err) } + if err := bdb.Update(context.TODO(), testNS, ones[0].Query(), operator.Unset(entity.Type)); err != nil { + t.Fatal(err) + } + if n, err := bdb.count(context.TODO(), testNS, map[string]string{}); err != nil { t.Fatal(err) } else if n != testN { @@ -202,6 +206,9 @@ func TestBoltDBUpdate(t *testing.T) { if err := bson.Unmarshal(j, &o); err != nil { t.Fatal(err) } + if o.Type != "" { + t.Fatalf("doc still has Type even though $unset called: %+v", o) + } if fmt.Sprint(ones[0]) == fmt.Sprint(o) { t.Fatal(ones[0], o) } @@ -210,6 +217,11 @@ func TestBoltDBUpdate(t *testing.T) { if fmt.Sprint(ones[0]) == fmt.Sprint(o) { t.Fatal(ones[0], o) } + ones[0].Type = "" + o.Type = "" + if fmt.Sprint(ones[0]) == fmt.Sprint(o) { + t.Fatal(ones[0], o) + } ones[0].Modified = 0 o.Modified = 0 if fmt.Sprint(ones[0]) != fmt.Sprint(o) { diff --git a/storage/graph.go b/storage/graph.go index 2a6d940..a4eebfd 100644 --- a/storage/graph.go +++ b/storage/graph.go @@ -3,9 +3,11 @@ package storage import ( "context" "fmt" + "local/dndex/config" "local/dndex/storage/driver" "local/dndex/storage/entity" "local/dndex/storage/operator" + "strings" "go.mongodb.org/mongo-driver/bson" ) @@ -15,9 +17,15 @@ type Graph struct { } func NewGraph() Graph { - mongo := driver.NewMongo() + var d driver.Driver + switch strings.ToLower(config.New().DriverType) { + case "mongo": + d = driver.NewMongo() + case "boltdb": + d = driver.NewBoltDB() + } return Graph{ - driver: mongo, + driver: d, } }