Encapsulate mongodb with typescript
At the moment of the epidemic, people do not leave their homes. For ordinary people, it is a patriotic expression to protect their health, not to get sick, and not to bring trouble to the medical staff and the country.
If you can keep learning during this time, it is a sign of loving yourself. In the face of the increasingly severe Internet industry, I also need to broaden my horizons and be ready to meet challenges. So I’ve been learning about KOA and typescript for a while, and it’s still a bit of a hole-in-a-wall, like trying to figure out if I can build my own KOA scaffolding. One of the first things I’ve done is wrap mongodb in typescript.
Why encapsulate mongodb
In fact, there is already a good third-party framework for mongoose, which is already very useful. Why do I have to encapsulate myself.
- For learning purposes, of course
- Self-packaging can be smaller and more flexible
The preparatory work
A few points need to be understood before encapsulation
- Typescript syntax (class, generics, interfaces)
- Asynchronous programming (promise, async, await)
- Design pattern (singleton pattern)
- Use of node-mongodb-native third library.
- Mongodb database syntax
Since I’m doing secondary packaging on a Node-mongodb-native basis, I definitely want to know how to use this framework. Git website: github.com/mongodb/nod… Look at the READme to see the basic usage of the library. Just note the following
const MongoClient = require('mongodb').MongoClient;
const assert = require('assert');
// Connection URL
const url = 'mongodb://localhost:27017';
// Database Name
const dbName = 'myproject';
// Use connect method to connect to the server
MongoClient.connect(url, function(err, client) {
assert.equal(null, err);
console.log("Connected successfully to server");
const db = client.db(dbName);
client.close();
});
Copy the code
This is an example of connecting to a database on the official website. This does not apply when your database has user permissions set.
const MongoClient = require('mongodb').MongoClient;
const assert = require('assert');
// Connection URL
const url = 'mongo: / / jgmiu: [email protected]:27017 / testdb'; // Database Name // const dbName ='myproject'; // Use connect method to connect to the server mongoclient.connect (url, mongoclient.connect)function(err, client) {
assert.equal(null, err);
console.log("Connected successfully to server"); const db = client.db(); // There is no need to follow the database name client.close(); });Copy the code
I am not good at English, so I did not find the method of how to connect by user authority in the official document. I tried this out.
Began to encapsulate
Once the preparation is done, the packaging begins step by step.
Create config file
Create the config.ts configuration file and set the parameters as follows
const config = {
url: 'mongo: / / jgmiu: [email protected]:27017 / testdb'
}
export default config
Copy the code
Introducing third-party libraries
Install the mongo
npm install --save mongodb
Copy the code
The DBI interface is created
Create the db.ts file and write the interface as follows
Interface DBI {// insert (collectionName:string, Doc :T):Promise< Boolean > Docs :T[]):Promise< Boolean > < Boolean > // Update (collectionName:string, Filter: object, update: object) : Promise < Boolean > / / find the find (collectionName: string, Aggregate (collectionName:string, Pipeline :object[]):Promise<any[]>}Copy the code
Create a singleton Db
To ensure only one instance of the database connection, we must use the singleton pattern on our own
class Db {
static instance:Db | null
static getInstance() {
if(! Db.instance) this.instance = new Db()return this.instance
}
constructor() {
console.log('constructor')
}
}
const db = Db.getinstance()
const db1 = Db.getinstance()
Copy the code
This is the simplest singleton pattern in which DB and DB1 are the same instance
Connecting to a Database
Now we want to connect to the database
import config from './config'
import mongodb from 'mongodb'
const MongoClient = mongodb.MongoClient
class Db implements DBI {
public client:mongodb.MongoClient | undefined
static instance:Db | null
static getInstance() {
if(! Db.instance) this.instance = new Db()return this.instance
}
constructor() {
console.log('constructor')
this.connection()
}
connection():Promise<mongodb.MongoClient> {
return new Promise<mongodb.MongoClient>((resolve, reject) => {
if(! this.client) { MongoClient.connect(config.url, {useUnifiedTopology:true}, (err, client) => {
if(err){
reject(err)
} else {
console.log('db server start success! ')
this.client = client
resolve(client)
}
})
} else {
resolve(this.client)
}
})
}
}
Copy the code
A couple of caveats
- Public client: mongo. MongoClient | undefined where the client must be stated as MongoClient type, if life will compile without using any type
- Connecting to the database is a time-consuming operation, so we check whether this.client already exists before connecting to the database. If so, we will not connect again.
- Note that Promise
is returned. In many of these methods, we return promises
So far we have dealt with multiple instances and multiple joins.
CRUD method implementation
We’ve done the preparation work, we’ve defined the interface, we’ve done the related processing for multiple instances and multiple connections, and then it’s time to implement add, delete, change, and check. This process is a lot of work, but it’s also the easiest. Here is an added example:
insert<T>(collectionName:string, doc:T):Promise<boolean> {
return new Promise<boolean>((resolve, reject) => {
this.connection().then((client) => {
const db = client.db()
const result = db.collection(collectionName).insert(doc, (err, result) => {
if(err){
resolve(false)
reject(err)
} else {
resolve(true)}})})})}Copy the code
Used in KOA
Koa uses the async syntax, and the methods we encapsulate are basically return promises, so it’s very easy to write
import Koa from 'koa'
import Router from 'koa-router'
import Db from './module/db'
const app = new Koa(),
router = new Router(),
db = new Db()
router.get('/', async (ctx) => {
const users = await db.find('users', {}) console.log(users) // Test add interface User{name:string} const result = await db.insertmany <User>('users',[{name: '888'}])
console.log(result)
ctx.body = 'index'
})
app.use(router.routes())
app.use(router.allowedMethods())
app.listen(3000, ()=>{
console.log('serve start on 3000')})Copy the code
That’s it. The full code can be viewed at: github.com/miujg/koa-t…