Upgrading think-mongo to Support MongoDB 4.x and Transactions in ThinkJS
This article explains how to upgrade the think-mongo module for ThinkJS to work with MongoDB 4.x, detailing API changes, new CRUD method mappings, transaction support, and provides code examples for adapting existing projects to the latest MongoDB features.
The author, a former front‑end engineer at Qiwu Group, describes the motivation for upgrading the think-mongo module: MongoDB has moved from version 2.x to 4.x, introducing transactions that many developers want to use.
Because the original think-mongo depends on the legacy mongodb driver (2.x), a simple version bump is impossible; the driver’s API has changed dramatically. The upgrade therefore requires refactoring the underlying connection logic, splitting the old Db methods into separate Client and Db classes.
// previous usage MongoClient.connect('mongodb://localhost:27017/test', (err, db) => { /* ... */ }); // new usage MongoClient.connect('mongodb://localhost:27017/test', (err, client) => { const db = client.db('test'); /* ... */ });
CRUD APIs have also been refined: collection.insert() becomes insertOne() and insertMany() ; collection.remove() becomes deleteOne() and deleteMany() ; collection.update() becomes updateOne() and updateMany() ; and collection.find(where, field) is split into find(where).project(field) . The module’s own add() and addMany() map naturally to the new insertOne() / insertMany() methods.
With MongoDB 4.x the driver now supports native transactions. Unlike SQL’s START TRANSACTION / COMMIT / ROLLBACK statements, MongoDB uses a session object. Each transaction creates a session, and all CRUD operations must receive this session so they are recorded in the same transaction.
const client = new MongoClient(uri); await client.connect(); const session = client.startSession(); try { session.startTransaction(); await client.db('think_db').add({name: 'thinkjs'}, {session}); await session.commitTransaction(); } catch (e) { await session.abortTransaction(); } finally { await session.endSession(); await client.close(); }
In a ThinkJS controller the author demonstrates how to wrap multiple model operations in a transaction using the provided transaction() helper, passing the session via the model’s options.session property so that subsequent CRUD calls automatically inherit the transaction context.
module.exports = class extends think.Controller { async indexAction() { const UserModel = this.mongo('user'); const PostModel = this.mongo('post'); await UserModel.transaction(async session => { PostModel.options.session = session; const userId = await UserModel.add({name: 'lizheming'}); await PostModel.add({userId, content: 'Hello World'}); }); } };
The article concludes with a note that the upgraded [email protected] already incorporates these changes, and developers using the native mongodb driver should adjust their code according to the listed API modifications.
360 Tech Engineering
Official tech channel of 360, building the most professional technology aggregation platform for the brand.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.