Skip to content

Commit 41425eb

Browse files
jakenierJaken
andauthored
feat(update): add Setfields function and method(#78)
Co-authored-by: Jaken <jaken@JakendeMacBook-Air.local>
1 parent 116bb88 commit 41425eb

File tree

6 files changed

+203
-0
lines changed

6 files changed

+203
-0
lines changed

builder/update/bson_build.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ func Set(key string, value any) bson.D {
5858
return bson.D{{Key: SetOp, Value: bson.D{{Key: key, Value: value}}}}
5959
}
6060

61+
func SetFields(value any) bson.D {
62+
return bson.D{{Key: SetOp, Value: value}}
63+
}
64+
6165
func Unset(keys ...string) bson.D {
6266
value := bson.D{}
6367
for i := range keys {

builder/update/bson_build_test.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,50 @@ func TestSet(t *testing.T) {
110110
})
111111
}
112112

113+
func TestSetFields(t *testing.T) {
114+
type FieldStruct struct {
115+
Name string `bson:"name,omitempty"`
116+
Age int `bson:"age,omitempty"`
117+
}
118+
119+
testCases := []struct {
120+
name string
121+
value any
122+
want bson.D
123+
}{
124+
{
125+
name: "nil value",
126+
value: nil,
127+
want: bson.D{bson.E{Key: "$set", Value: nil}},
128+
},
129+
{
130+
name: "string value",
131+
value: "Alice",
132+
want: bson.D{bson.E{Key: "$set", Value: "Alice"}},
133+
},
134+
{
135+
name: "map value",
136+
value: map[string]any{"name": "Alice"},
137+
want: bson.D{bson.E{Key: "$set", Value: map[string]any{"name": "Alice"}}},
138+
},
139+
{
140+
name: "bson value",
141+
value: bson.D{bson.E{Key: "name", Value: "Alice"}},
142+
want: bson.D{bson.E{Key: "$set", Value: bson.D{bson.E{Key: "name", Value: "Alice"}}}},
143+
},
144+
{
145+
name: "struct value",
146+
value: FieldStruct{Name: "Alice", Age: 18},
147+
want: bson.D{bson.E{Key: "$set", Value: FieldStruct{Name: "Alice", Age: 18}}},
148+
},
149+
}
150+
for _, tc := range testCases {
151+
t.Run(tc.name, func(t *testing.T) {
152+
assert.Equal(t, tc.want, SetFields(tc.value))
153+
})
154+
}
155+
}
156+
113157
func TestUnset(t *testing.T) {
114158
testCases := []struct {
115159
name string

builder/update/field_update_builder.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,15 @@ func (b *fieldUpdateBuilder) Set(key string, value any) *Builder {
3030
return b.parent
3131
}
3232

33+
func (b *fieldUpdateBuilder) SetFields(value any) *Builder {
34+
e := bson.E{Key: SetOp, Value: value}
35+
if !b.parent.tryMergeValue(SetOp, e) {
36+
b.parent.data = append(b.parent.data, e)
37+
}
38+
39+
return b.parent
40+
}
41+
3342
func (b *fieldUpdateBuilder) Unset(keys ...string) *Builder {
3443
value := bson.D{}
3544
for i := range keys {

builder/update/field_update_builder_test.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,63 @@ func Test_fieldUpdateBuilder_Set(t *testing.T) {
3333
})
3434
}
3535

36+
func Test_fieldUpdateBuilder_SetFields(t *testing.T) {
37+
testCases := []struct {
38+
name string
39+
value any
40+
want bson.D
41+
}{
42+
{
43+
name: "nil value",
44+
value: nil,
45+
want: bson.D{bson.E{Key: "$set", Value: nil}},
46+
},
47+
{
48+
name: "string value",
49+
value: "Alice",
50+
want: bson.D{bson.E{Key: "$set", Value: "Alice"}},
51+
},
52+
{
53+
name: "map value",
54+
value: map[string]any{"name": "Alice"},
55+
want: bson.D{bson.E{Key: "$set", Value: map[string]any{"name": "Alice"}}},
56+
},
57+
{
58+
name: "bson value",
59+
value: bson.D{bson.E{Key: "name", Value: "Alice"}},
60+
want: bson.D{bson.E{Key: "$set", Value: bson.D{bson.E{Key: "name", Value: "Alice"}}}},
61+
},
62+
{
63+
name: "pointer struct value",
64+
value: &bson.D{bson.E{Key: "name", Value: "Alice"}},
65+
want: bson.D{bson.E{Key: "$set", Value: &bson.D{bson.E{Key: "name", Value: "Alice"}}}},
66+
},
67+
{
68+
name: "struct value",
69+
value: struct{ Name string }{Name: "Alice"},
70+
want: bson.D{bson.E{Key: "$set", Value: struct{ Name string }{Name: "Alice"}}},
71+
},
72+
}
73+
74+
for _, tc := range testCases {
75+
t.Run(tc.name, func(t *testing.T) {
76+
assert.Equal(t, tc.want, NewBuilder().SetFields(tc.value).Build())
77+
})
78+
}
79+
80+
t.Run("multiple set_fields", func(t *testing.T) {
81+
assert.Equal(t, bson.D{{Key: "$set", Value: struct{ Name string }{Name: "cmy"}}, {Key: "$set", Value: struct{ Age int64 }{Age: 24}}}, NewBuilder().SetFields(struct{ Name string }{Name: "cmy"}).SetFields(struct{ Age int64 }{Age: 24}).Build())
82+
})
83+
84+
t.Run("set_fields with struct value and set single operation", func(t *testing.T) {
85+
assert.Equal(t, bson.D{{Key: "$set", Value: struct{ Name string }{Name: "cmy"}}, {Key: "$set", Value: bson.D{bson.E{Key: "name", Value: "cmy"}}}}, NewBuilder().SetFields(struct{ Name string }{Name: "cmy"}).Set("name", "cmy").Build())
86+
})
87+
88+
t.Run("set_fields with pointer struct value and set multiple operation", func(t *testing.T) {
89+
assert.Equal(t, bson.D{{Key: "$set", Value: struct{ Name string }{Name: "cmy"}}, {Key: "$set", Value: bson.D{bson.E{Key: "name", Value: "cmy"}, bson.E{Key: "age", Value: 24}}}}, NewBuilder().SetFields(struct{ Name string }{Name: "cmy"}).Set("name", "cmy").Set("age", 24).Build())
90+
})
91+
}
92+
3693
func Test_fieldUpdateBuilder_Unset(t *testing.T) {
3794
assert.Equal(t, bson.D{{Key: "$unset", Value: bson.D{}}}, NewBuilder().Unset().Build())
3895
assert.Equal(t, bson.D{{Key: "$unset", Value: bson.D{bson.E{Key: "name", Value: ""}}}}, NewBuilder().Unset("name").Build())

updater/types.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,13 @@ type User struct {
5656
UnknownField string `bson:"-"`
5757
}
5858

59+
type UserTestField struct {
60+
Id string `bson:"_id"`
61+
Name string `bson:"name"`
62+
Age int64 `bson:"age,omitempty"`
63+
UnknownField string `bson:"-"`
64+
}
65+
5966
type TestUser struct {
6067
ID bson.ObjectID `bson:"_id,omitempty"`
6168
Name string `bson:"name"`

updater/updater_e2e_test.go

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,88 @@ func TestUpdater_e2e_UpdateOne(t *testing.T) {
222222
return assert.NoError(t, err)
223223
},
224224
},
225+
226+
{
227+
name: "update one success when update use set_fields with struct",
228+
before: func(ctx context.Context, t *testing.T) {
229+
insertResult, err := collection.InsertOne(ctx, User{Id: "1", Name: "Mingyong Chen", Age: 18})
230+
assert.NoError(t, err)
231+
assert.NotNil(t, insertResult.InsertedID)
232+
},
233+
after: func(ctx context.Context, t *testing.T) {
234+
deleteResult, err := collection.DeleteOne(ctx, query.NewBuilder().Eq("name", "chenmingyong").Eq("age", 19).Build())
235+
assert.NoError(t, err)
236+
assert.Equal(t, int64(1), deleteResult.DeletedCount)
237+
},
238+
ctx: context.Background(),
239+
filter: query.Id("1"),
240+
updates: update.SetFields(User{Id: "1", Name: "chenmingyong", Age: 19}),
241+
want: &mongo.UpdateResult{MatchedCount: 1, ModifiedCount: 1, UpsertedCount: 0, UpsertedID: nil, Acknowledged: true},
242+
wantErr: func(t assert.TestingT, err error, i ...interface{}) bool {
243+
return assert.NoError(t, err)
244+
},
245+
},
246+
{
247+
name: "update one success when update use set_fields with one field struct",
248+
before: func(ctx context.Context, t *testing.T) {
249+
insertResult, err := collection.InsertOne(ctx, UserTestField{Id: "1", Name: "Mingyong Chen", Age: 18})
250+
assert.NoError(t, err)
251+
assert.NotNil(t, insertResult.InsertedID)
252+
},
253+
after: func(ctx context.Context, t *testing.T) {
254+
deleteResult, err := collection.DeleteOne(ctx, query.NewBuilder().Eq("name", "chenmingyong").Eq("age", 18).Build())
255+
assert.NoError(t, err)
256+
assert.Equal(t, int64(1), deleteResult.DeletedCount)
257+
},
258+
ctx: context.Background(),
259+
filter: query.Id("1"),
260+
updates: update.SetFields(UserTestField{Id: "1", Name: "chenmingyong"}),
261+
want: &mongo.UpdateResult{MatchedCount: 1, ModifiedCount: 1, UpsertedCount: 0, UpsertedID: nil, Acknowledged: true},
262+
wantErr: func(t assert.TestingT, err error, i ...interface{}) bool {
263+
return assert.NoError(t, err)
264+
},
265+
},
266+
{
267+
name: "update one success when update use set_fields with struct pointer",
268+
before: func(ctx context.Context, t *testing.T) {
269+
insertResult, err := collection.InsertOne(ctx, User{Id: "1", Name: "Mingyong Chen", Age: 18})
270+
assert.NoError(t, err)
271+
assert.NotNil(t, insertResult.InsertedID)
272+
},
273+
after: func(ctx context.Context, t *testing.T) {
274+
deleteResult, err := collection.DeleteOne(ctx, query.NewBuilder().Eq("name", "chenmingyong").Eq("age", 19).Build())
275+
assert.NoError(t, err)
276+
assert.Equal(t, int64(1), deleteResult.DeletedCount)
277+
},
278+
ctx: context.Background(),
279+
filter: query.Id("1"),
280+
updates: update.SetFields(&User{Id: "1", Name: "chenmingyong", Age: 19}),
281+
want: &mongo.UpdateResult{MatchedCount: 1, ModifiedCount: 1, UpsertedCount: 0, UpsertedID: nil, Acknowledged: true},
282+
wantErr: func(t assert.TestingT, err error, i ...interface{}) bool {
283+
return assert.NoError(t, err)
284+
},
285+
},
286+
{
287+
name: "update one success when update use set_fields with map",
288+
before: func(ctx context.Context, t *testing.T) {
289+
insertResult, err := collection.InsertOne(ctx, User{Id: "1", Name: "Mingyong Chen", Age: 18})
290+
assert.NoError(t, err)
291+
assert.NotNil(t, insertResult.InsertedID)
292+
},
293+
after: func(ctx context.Context, t *testing.T) {
294+
deleteResult, err := collection.DeleteOne(ctx, query.NewBuilder().Eq("name", "chenmingyong").Eq("age", 19).Build())
295+
assert.NoError(t, err)
296+
assert.Equal(t, int64(1), deleteResult.DeletedCount)
297+
},
298+
ctx: context.Background(),
299+
filter: query.Id("1"),
300+
updates: update.SetFields(map[string]any{"name": "chenmingyong", "age": 19}),
301+
want: &mongo.UpdateResult{MatchedCount: 1, ModifiedCount: 1, UpsertedCount: 0, UpsertedID: nil, Acknowledged: true},
302+
wantErr: func(t assert.TestingT, err error, i ...interface{}) bool {
303+
return assert.NoError(t, err)
304+
},
305+
},
306+
225307
{
226308
name: "upserted count is 1",
227309
before: func(ctx context.Context, t *testing.T) {

0 commit comments

Comments
 (0)