diff --git a/db/mongo.go b/db/mongo.go index 841d821..6f0fda3 100644 --- a/db/mongo.go +++ b/db/mongo.go @@ -72,6 +72,66 @@ func (c *mongoCollection) InsertOne(ctx context.Context, key interface{}, data i return nil } +// inserts or updates one entry with given key and data to the collection +// acts based on the flag passed for upsert +// returns errors if entry not found while upsert flag is false or if +// there is a connection error with the database server +func (c *mongoCollection) UpdateOne(ctx context.Context, key interface{}, data interface{}, upsert bool) error { + if data == nil { + return errors.Wrap(errors.InvalidArgument, "db Insert error: No data to store") + } + if key == nil { + return errors.Wrap(errors.InvalidArgument, "db Insert error: No Key specified to store") + } + + opts := options.Update().SetUpsert(upsert) + resp, err := c.col.UpdateOne( + ctx, + bson.M{"_id": key}, + bson.D{ + {Key: "$set", Value: data}, + }, + opts) + + if err != nil { + return err + } + + // check there should be at least one entry in matched count + // or upserted count to not return an error here + if resp.MatchedCount != 0 && resp.UpsertedCount != 0 { + return errors.Wrap(errors.NotFound, "No Document found") + } + + return nil +} + +// Find one entry from the store collection for the given key, where the data +// value is returned based on the object type passed to it +func (c *mongoCollection) FindOne(ctx context.Context, key interface{}, data interface{}) error { + resp := c.col.FindOne(ctx, bson.M{"_id": key}) + // decode the value returned by the mongodb client into the data + // object passed by the caller + if err := resp.Decode(data); err != nil { + // TODO(prabhjot) might have to identify not found error + return err + } + return nil +} + +// Find multiple entries from the store collection for the given filter, where the data +// value is returned as a list based on the object type passed to it +func (c *mongoCollection) FindMany(ctx context.Context, filter interface{}, data interface{}) error { + cursor, err := c.col.Find(ctx, filter) + if err != nil { + return err + } + if err = cursor.All(ctx, data); err != nil { + return err + } + return nil +} + // remove one entry from the collection matching the given key func (c *mongoCollection) DeleteOne(ctx context.Context, key interface{}) error { resp, err := c.col.DeleteOne(ctx, bson.M{"_id": key}) diff --git a/db/mongo_test.go b/db/mongo_test.go index 7b9aa75..8652039 100644 --- a/db/mongo_test.go +++ b/db/mongo_test.go @@ -12,8 +12,13 @@ type MyKey struct { Name string } +type InternaData struct { + Test string +} + type MyData struct { Desc string + Val *InternaData } func Test_ClientConnection(t *testing.T) { @@ -46,12 +51,35 @@ func Test_ClientConnection(t *testing.T) { } data := &MyData{ Desc: "sample-description", + Val: &InternaData{ + Test: "abc", + }, } + err = col.InsertOne(context.Background(), key, data) if err != nil { t.Errorf("failed to insert an entry to collection Error: %s", err) } + val := &MyData{} + err = col.FindOne(context.Background(), key, val) + if err != nil { + t.Errorf("failed to find the entry Error: %s", err) + } + + data.Desc = "new description" + data.Val.Test = "xyz" + err = col.UpdateOne(context.Background(), key, data, false) + if err != nil { + t.Errorf("failed to update an entry to collection Error: %s", err) + } + + val = &MyData{} + err = col.FindOne(context.Background(), key, val) + if err != nil { + t.Errorf("failed to find the entry Error: %s", err) + } + err = col.DeleteOne(context.Background(), key) if err != nil { t.Errorf("failed to delete entry using key Error: %s", err) @@ -61,6 +89,16 @@ func Test_ClientConnection(t *testing.T) { if err == nil { t.Errorf("attemptting delete on already deleted entry, but didn't receive expected error") } + + err = col.UpdateOne(context.Background(), key, data, true) + if err != nil { + t.Errorf("failed to update an entry to collection Error: %s", err) + } + + err = col.DeleteOne(context.Background(), key) + if err != nil { + t.Errorf("failed to delete entry using key Error: %s", err) + } }) t.Run("InValid_Port", func(t *testing.T) { diff --git a/db/store.go b/db/store.go index b670aa9..850ad42 100644 --- a/db/store.go +++ b/db/store.go @@ -15,6 +15,19 @@ type StoreCollection interface { // insert one entry to the collection for the given key and data InsertOne(ctx context.Context, key interface{}, data interface{}) error + // update one entry in the collection for the given key and data + // if upsert flag is set, it would insert an entry if it doesn't + // exist while updating + UpdateOne(ctx context.Context, key interface{}, data interface{}, upsert bool) error + + // Find one entry from the store collection for the given key, where the data + // value is returned based on the object type passed to it + FindOne(ctx context.Context, key interface{}, data interface{}) error + + // Find multiple entries from the store collection for the given filter, where the data + // value is returned as a list based on the object type passed to it + FindMany(ctx context.Context, filter interface{}, data interface{}) error + // remove one entry from the collection matching the given key DeleteOne(ctx context.Context, key interface{}) error }