I’m looking for way to execute multiple statement in mongodb in a transaction. All or nothing kind of scenario. To make it easy to understand
trxTest> db.users.find({})
[ { _id: ObjectId("64ad882f451d9a5fc930eeb7"), name: 'werain' } ]
trxTest>
I’m looking to insert the multiple documents and one of the document conflict the uniquenss key on name ‘werain’
client, err := mongo.Connect(context.Background(), options.Client().ApplyURI("mongodb://localhost:27017"))
if err != nil {
panic(err)
}
DB := client.Database("trxTest")
coll1 := DB.Collection("users")
session, err := client.StartSession()
if err != nil {
panic(err)
}
defer session.EndSession(context.Background())
_, err = session.WithTransaction(context.Background(), func(ctx mongo.SessionContext) (interface{}, error) {
_, err = coll1.InsertOne(context.Background(), bson.M{"name": "vikas"})
if err != nil {
return nil, err
}
fmt.Println("vikas is inserted")
_, err = coll1.InsertOne(context.Background(), bson.M{"name": "sriram"})
if err != nil {
return nil, err
}
fmt.Println("sriram is inserted")
fmt.Println("inserting is werain again")
_, err = coll1.InsertOne(context.Background(), bson.M{"name": "werain"}) // This is where the transaction should failed
if err != nil {
return nil, err
}
fmt.Println("werain is inserted")
return nil, nil
}, nil)
if err != nil {
fmt.Println("got trx error", err)
}
Here how the code looks
I was accepting the database would rollback my 2 entry for users with name "vikas" and "sriram"
but I see this
trxTest> db.users.find({})
[
{ _id: ObjectId("64ad882f451d9a5fc930eeb7"), name: 'werain' },
{ _id: ObjectId("64ad8c65f63f3f2b48f66169"), name: 'vikas' },
{ _id: ObjectId("64ad8c66f63f3f2b48f6616a"), name: 'sriram' }
]
Error
vikas is inserted
sriram is inserted
inserting is werain again
got error write exception: write errors: [E11000 duplicate key error collection: trxTest.users index: name_1 dup key: { name: "werain" }]
db version v6.0.1
Build Info: {
"version": "6.0.1",
"gitVersion": "32f0f9c88dc44a2c8073a5bd47cf779d4bfdee6b",
"modules": [],
"allocator": "system",
"environment": {
"distarch": "aarch64",
"target_arch": "aarch64"
}
}
2
Answers
As pointed out by @burak-serdar, Transaction numbers are only allowed on a replica set member or mongos. See also PyMongo transaction error:Transaction numbers are only allowed on a replica set member or mongos.
Besides that, the doc for the
WithTransaction
method of the mongo.Session interface states thatSo you should replace all the following calls
with
For this case, and not having access to Transactions (as pointed out by @Zeke Lu amd @Burak Serdar) your best option is to use a bulk operation like Insert Many
This way, you’ll get a
BulkWriteError
for the duplicate_id
key, but all the others should insert. For this to work, use an unordered insertMany operation.