3. MongoDB# We use MongoDB to store user account information and files
3.1 Mongoose# We use Mongoose for modeling the data, is an object modeling tool for MongoDB.
The reference is here
3.1.1 Preload# To preload the model, firstly import the configuration . Also import the mongoose npm module
File location: loaders\mongoDB.js
Copy const config = require ( '../config' ) ;
const { sleep } = require ( '../utils' )
const mongoose = require ( 'mongoose' ) ;
mongoose . connect ( config . mongodb . addr , {
useNewUrlParser : true ,
useUnifiedTopology : true ,
useFindAndModify : false ,
useCreateIndex : true ,
} ) ;
Then, connect to MongoDB and add an error handler. Also, we need to get log from console to make sure MongoDB is connected.
Copy mongoose . connect ( config . mongodb . addr , {
useNewUrlParser : true ,
useUnifiedTopology : true ,
useFindAndModify : false ,
useCreateIndex : true ,
} ) ;
const db = mongoose . connection ;
db . on ( 'error' , console . error . bind ( console , 'connection error:' ) ) ;
db . once ( 'open' , function ( ) {
console . log ( 'MongoDB connected.' )
} ) ;
3.1.2 Modeling# To create a mongoDB model by Mongoose, you can do the following:
First, in a class file of /model folder, load the mooge NPM package
Copy const mongoose = require ( 'mongoose' ) ;
const Schema = mongoose . Schema ;
Create a schema:
Copy const UserSchema = new Schema ( {
username : { type : String , unique : true , required : true } ,
email : String ,
} , { timestamps : { createdAt : 'created_at' , updatedAt : 'updated_at' } } ) ;
Model the schema:
Copy const MongoDBUserModel = mongoose . model ( "User" , UserSchema , "User" ) ;
Then you can insert the data in the database by following the schema:
Copy const mongoDBModel = new MongoDBUserModel ( {
username : "exampleuser" ,
email : "test@example.com" ,
} )
await mongoDBModel . save ( )
If you want to see other detail you need, you can view the reference here .
3.1.3 Queries# Mongoose provides functions to find, update and delete data, the following are examples
Find documents in a collection
Copy const users = await MongoDBUserModel . find ( { } )
Find one specific by giving a condition filter
Copy const user = await MongoDBUserModel . findOne ( { username : "exampleuser" ,
email : "test@example.com" } )
Update data by giving a condition filter
Copy await MongoDBUserModel . findOneAndUpdate ( { username : "exampleuser" } , { email : "test2@example.com" } )
Delete data by giving a condition filter
Copy const user = await MongoDBUserModel . deleteOne ( { username : "exampleuser" ,
email : "test@example.com" } )
If you want to see other details you need, you can view the reference
here .
3.2 Grid-FS# Grid-FS is a file storage tool for MongoDB, the reference is here . For
Mongoose, we use Mongoose GridFS .
3.2.1 Setting and preload# In the mongodb loader file \loaders\mongoDB.js, on top of the original loader setting , import the NPM package
Copy const { createModel } = require ( 'mongoose-gridfs' ) ;
Load the attachment
Copy let Attachment ;
db . once ( 'open' , function ( ) {
...
Attachment = createModel ( {
modelName : 'Attachment' ,
connection : db
} ) ;
} ) ;
Implement a asynchronous function and load the attachment
Copy async function getAttachment ( ) {
while ( ! Attachment ) {
await sleep ( 100 ) ;
}
return Attachment ;
}
module . exports = { getAttachment } ;
After that, we can implement the function to be able to upload and download file
from MongoDB.
3.2.2 Upload file# The following is the implementation of upload file, you can read details here .
Currently, it is only used to store resources for opportunity listings.
Copy const Attachment = await getAttachment ( ) ;
let closedByServer ;
const writeStream = Attachment . bucket . writeFile ( { filename , contentType } , readStream ) ;
return new Promise ( ( resolve , reject ) => {
writeStream . on ( 'finish' , async ( file ) => {
const fileData = new MongoDBFileModel ( { fileId : file . _id } ) ;
await fileData . save ( ) ;
closedByServer = true ;
resolve ( file . _id ) ;
} ) ;
writeStream . on ( 'error' , reject ) ;
readStream . on ( 'close' , ( ) => {
if ( ! closedByServer )
writeStream . abort ( ) ;
} ) ;
readStream . on ( 'error' , reject ) ;
} )
After the file is uploaded, it will be given file ID to help with getting the file later on. To save the file ID, we can
create different mongoDB model to store the file ID.
Copy const MongoDBFileSchema = Schema ( {
fileId : { type : String , unique : true } ,
uploadDate : { type : Date , default : Date . now ( ) }
} ) ;
const MongoDBFileModel = mongoose . model ( 'MongoDBFile' , MongoDBFileSchema , 'MongoDBFile' )
3.2.3 Get file# The following is the implementation of download file, you can read details here
Copy async function getFile ( req , res , next ) {
const { fileId } = req . params ;
const Attachment = await getAttachment ( )
try {
const file = await Attachment . findById ( fileId ) ;
const readStream = Attachment . bucket . readFile ( { _id : ObjectId ( fileId ) } )
res . set ( 'Content-Type' , file . contentType ) ;
readStream . pipe ( res ) . on ( 'error' , function ( err ) {
res . json ( { error : err } )
} )
} catch ( e ) {
next ( e ) ;
}
}
3.3 MongoDB Compass# MongoDB Compass provides a user-friendly UI to visualize the MongoDB, you can view the detail
here .