@@ -15,6 +15,7 @@ import (
15
15
16
16
"go.mongodb.org/mongo-driver/bson"
17
17
"go.mongodb.org/mongo-driver/bson/primitive"
18
+ "go.mongodb.org/mongo-driver/event"
18
19
"go.mongodb.org/mongo-driver/internal/testutil/assert"
19
20
"go.mongodb.org/mongo-driver/mongo"
20
21
"go.mongodb.org/mongo-driver/mongo/integration/mtest"
@@ -1154,6 +1155,105 @@ func TestCollection(t *testing.T) {
1154
1155
mt .Fatalf ("expected BulkWrite error %v, got %v" , mongo .ErrUnacknowledgedWrite , err )
1155
1156
}
1156
1157
})
1158
+ mt .Run ("insert and delete with batches" , func (mt * mtest.T ) {
1159
+ // grouped together because delete requires the documents to be inserted
1160
+ numDocs := 100050
1161
+ var insertModels []mongo.WriteModel
1162
+ var deleteModels []mongo.WriteModel
1163
+ for i := 0 ; i < numDocs ; i ++ {
1164
+ d := bson.D {
1165
+ {"a" , int32 (i )},
1166
+ {"b" , int32 (i * 2 )},
1167
+ {"c" , int32 (i * 3 )},
1168
+ }
1169
+ insertModels = append (insertModels , mongo .NewInsertOneModel ().SetDocument (d ))
1170
+ deleteModels = append (deleteModels , mongo .NewDeleteOneModel ().SetFilter (bson.D {}))
1171
+ }
1172
+ mt .ClearEvents ()
1173
+ res , err := mt .Coll .BulkWrite (mtest .Background , insertModels )
1174
+ assert .Nil (mt , err , "BulkWrite error: %v" , err )
1175
+ assert .Equal (mt , int64 (numDocs ), res .InsertedCount , "expected %v inserted documents, got %v" , numDocs , res .InsertedCount )
1176
+ mt .FilterStartedEvents (func (evt * event.CommandStartedEvent ) bool {
1177
+ return evt .CommandName == "insert"
1178
+ })
1179
+ // MaxWriteBatchSize changed between 3.4 and 3.6, so there isn't a given number of batches that this will be split into
1180
+ inserts := len (mt .GetAllStartedEvents ())
1181
+ assert .True (mt , inserts > 1 , "expected multiple batches, got %v" , inserts )
1182
+
1183
+ mt .ClearEvents ()
1184
+ res , err = mt .Coll .BulkWrite (mtest .Background , deleteModels )
1185
+ assert .Nil (mt , err , "BulkWrite error: %v" , err )
1186
+ assert .Equal (mt , int64 (numDocs ), res .DeletedCount , "expected %v deleted documents, got %v" , numDocs , res .DeletedCount )
1187
+ mt .FilterStartedEvents (func (evt * event.CommandStartedEvent ) bool {
1188
+ return evt .CommandName == "delete"
1189
+ })
1190
+ // MaxWriteBatchSize changed between 3.4 and 3.6, so there isn't a given number of batches that this will be split into
1191
+ deletes := len (mt .GetAllStartedEvents ())
1192
+ assert .True (mt , deletes > 1 , "expected multiple batches, got %v" , deletes )
1193
+ })
1194
+ mt .Run ("update with batches" , func (mt * mtest.T ) {
1195
+ var models []mongo.WriteModel
1196
+ numModels := 100050
1197
+
1198
+ // it's significantly faster to upsert one model and modify the rest than to upsert all of them
1199
+ for i := 0 ; i < numModels - 1 ; i ++ {
1200
+ update := bson.D {
1201
+ {"$set" , bson.D {
1202
+ {"a" , int32 (i + 1 )},
1203
+ {"b" , int32 (i * 2 )},
1204
+ {"c" , int32 (i * 3 )},
1205
+ }},
1206
+ }
1207
+ model := mongo .NewUpdateOneModel ().
1208
+ SetFilter (bson.D {{"a" , int32 (i )}}).
1209
+ SetUpdate (update ).SetUpsert (true )
1210
+ models = append (models , model )
1211
+ }
1212
+ // add one last upsert
1213
+ models = append (models , mongo .NewUpdateOneModel ().
1214
+ SetFilter (bson.D {{"x" , int32 (1 )}}).
1215
+ SetUpdate (bson.D {{"$set" , bson.D {{"x" , int32 (1 )}}}}).
1216
+ SetUpsert (true ),
1217
+ )
1218
+
1219
+ mt .ClearEvents ()
1220
+ res , err := mt .Coll .BulkWrite (mtest .Background , models )
1221
+ assert .Nil (mt , err , "BulkWrite error: %v" , err )
1222
+
1223
+ mt .FilterStartedEvents (func (evt * event.CommandStartedEvent ) bool {
1224
+ return evt .CommandName == "update"
1225
+ })
1226
+ // MaxWriteBatchSize changed between 3.4 and 3.6, so there isn't a given number of batches that this will be split into
1227
+ updates := len (mt .GetAllStartedEvents ())
1228
+ assert .True (mt , updates > 1 , "expected multiple batches, got %v" , updates )
1229
+
1230
+ assert .Equal (mt , int64 (numModels - 2 ), res .ModifiedCount , "expected %v modified documents, got %v" , numModels - 2 , res .ModifiedCount )
1231
+ assert .Equal (mt , int64 (numModels - 2 ), res .MatchedCount , "expected %v matched documents, got %v" , numModels - 2 , res .ModifiedCount )
1232
+ assert .Equal (mt , int64 (2 ), res .UpsertedCount , "expected %v upserted documents, got %v" , 2 , res .UpsertedCount )
1233
+ assert .Equal (mt , 2 , len (res .UpsertedIDs ), "expected %v upserted ids, got %v" , 2 , len (res .UpsertedIDs ))
1234
+
1235
+ // find the upserted documents and check their contents
1236
+ id1 , ok := res .UpsertedIDs [0 ]
1237
+ assert .True (mt , ok , "expected id at key 0" )
1238
+ id2 , ok := res .UpsertedIDs [int64 (numModels - 1 )]
1239
+ assert .True (mt , ok , "expected id at key %v" , numModels - 1 )
1240
+
1241
+ doc , err := mt .Coll .FindOne (mtest .Background , bson.D {{"_id" , id1 }}).DecodeBytes ()
1242
+ a , ok := doc .Lookup ("a" ).Int32OK ()
1243
+ assert .True (mt , ok , "expected a to be an int32" )
1244
+ assert .Equal (mt , int32 (numModels - 1 ), a , "expected a value %v, got %v" , numModels - 1 , a )
1245
+ b , ok := doc .Lookup ("b" ).Int32OK ()
1246
+ assert .True (mt , ok , "expected b to be an int32" )
1247
+ assert .Equal (mt , int32 ((numModels - 2 )* 2 ), b , "expected b value %v, got %v" , (numModels - 2 )* 2 , b )
1248
+ c , ok := doc .Lookup ("c" ).Int32OK ()
1249
+ assert .True (mt , ok , "expected c to be an int32" )
1250
+ assert .Equal (mt , int32 ((numModels - 2 )* 3 ), c , "expected b value %v, got %v" , (numModels - 2 )* 3 , c )
1251
+
1252
+ doc , err = mt .Coll .FindOne (mtest .Background , bson.D {{"_id" , id2 }}).DecodeBytes ()
1253
+ x , ok := doc .Lookup ("x" ).Int32OK ()
1254
+ assert .True (mt , ok , "expected x to be an int32" )
1255
+ assert .Equal (mt , int32 (1 ), x , "expected a value 1, got %v" , x )
1256
+ })
1157
1257
})
1158
1258
}
1159
1259
0 commit comments