1. MongoDB Fundamentals
Relational vs Non-Relational Databases
Relational databases rely on SQL for operations and maintain strict ACID (Atomicity, Consistency, Isolation, Durability) compliance through transaction mechanisms. Common examples include MySQL, SQL Server, DB2, and Oracle.
Non-relational databases, often referred to as "Not Only SQL," prioritize flexibility, lightweight architecture, and high efficiency. Examples include MongoDB, HBase, and Redis.
MongoDB is frequently chosen for its unique data handling: it can load hot data into memory for extremely fast read operations (though this consumes significant RAM). Using BSON for storage provides excellent support for JSON-like data structures and allows for flexible schema modifications. Its document-based storage is intuitive, and it offers robust horizontal scaling through sharding and reliable automatic failover.
| SQL Concept | MongoDB Concept | Description |
|---|---|---|
| database | database | Database instance |
| table | collection | Database table / Collection |
| row | document | Data record / Document |
| column | field | Data field / Attribute |
| index | index | Index |
| table joins | N/A | Table joins are not supported in MongoDB |
| primary key | primary key | Primary key; MongoDB auto-sets the _id field |
Installation
Download and install the community edition from the official MongoDB documentation.
Starting the Server
Windows:
mongod --dbpath d:/data/db
mongo
macOS:
mongod --config /usr/local/etc/mongod.conf
mongo
Command Line Operations
Database Management:
// Check help commands
help
db.help()
// Switch to or create a database named 'music'
use music
// List all databases
show dbs
// Check current database
db.getName()
// Display database status and version
db.stats()
db.version()
// Drop current database
db.dropDatabase()
Collection Management:
// Create a capped collection (max 5MB, 5000 docs)
db.createCollection("collName", {size: 5242880, capped: true, max: 5000});
// Get specific collection
db.getCollection("account");
// List all collections
db.getCollectionNames();
// Drop a collection
db.users.drop();
CRUD Operations:
// Create
db.users.save({name: "zhangsan", age: 25, sex: true});
db.users.insertMany([{name: "lisi", age: 30}, {name: "wangwu", age: 22}]);
// Update (equivalent to SQL: UPDATE users SET name="changeName" WHERE age=25)
db.users.update({age: 25}, {$set: {name: "changeName"}}, false, true);
// Delete
db.users.remove({age: 132});
// Read all
db.userInfo.find();
// Distinct values
db.userInfo.distinct("name");
// Comparison queries
db.userInfo.find({age: {$gt: 22}}); // age > 22
db.userInfo.find({age: {$gte: 23, $lte: 26}}); // age between 23 and 26
// Regex (Like %mongo%)
db.userInfo.find({name: /mongo/});
// Projection (Select specific fields)
db.userInfo.find({age: {$gt: 25}}, {name: 1, age: 1});
// Sorting and Pagination
db.userInfo.find().sort({age: -1}); // Descending
db.userInfo.find().skip(5).limit(5); // Skip 5, limit 5
// OR condition
db.userInfo.find({$or: [{age: 22}, {age: 25}]});
// Count
db.userInfo.find({age: {$gte: 25}}).count();
GUI Tools
Popular tools for managing MongoDB visually include Robo 3T (formerly Robomongo), and adminMongo.
Integrating with Node.js (Mongoose)
Connection:
const mongoose = require("mongoose");
mongoose.connect("mongodb://127.0.0.1:27017/company-system");
Schema Definition:
const mongoose = require("mongoose");
const { Schema } = mongoose;
const StaffSchemaDefinition = {
username: String,
password: String,
gender: Number,
introduction: String,
avatar: String,
role: Number
};
const StaffModel = mongoose.model("staff", new Schema(StaffSchemaDefinition));
module.exports = StaffModel;
Operations:
// Create
StaffModel.create({ introduction, username, gender, avatar, password, role });
// Read with pagination and sorting
StaffModel.find(
{ username: "kerwin" },
["username", "role", "introduction", "password"]
).sort({ createTime: -1 }).skip(10).limit(10);
// Update
StaffModel.updateOne({ _id }, { introduction, username, gender, avatar });
// Delete
StaffModel.deleteOne({ _id });
2. API Design and Architecutre
RESTful Conventions
RESTful architecture dictates that URLs should represent resources (nouns) while HTTP methods represent actions (verbs).
GET /api/staff- Retrieve listPOST /api/staff- Create new entryPUT /api/staff/{id}- Update entryDELETE /api/staff/{id}- Remove entry
Common filtering parameters:
?limit=10: Limit results?page=2&per_page=100: Pagination?sortby=name&order=asc: Sorting
Business Logic Layering (MVC)
A standard Node.js application often separates concerns into layers:
- Entry (index.js): Receives client requests.
- Routing (router.js): Distributes requests to the Controller.
- Controller (controller.js): Handles business logic and communicates between Model and View.
- Model (model.js): Handles data logic (Database CRUD).
- View (views): Presents the UI (HTML).
3. Authentication Strategies
Cookie & Session
HTTP is stateless. To maintain user sessions, the server generates a Session ID upon login, stores it (e.g., in MongoDB), and sends it to the browser via a Cookie. Subsequent requests from the browser include this Cookie, allowing the server to validate the session.
const express = require("express");
const session = require("express-session");
const MongoStore = require("connect-mongo");
const app = express();
app.use(session({
secret: "complex_secret_key",
resave: true,
saveUninitialized: true,
cookie: { maxAge: 1000 * 60 * 10 },
rolling: true,
store: MongoStore.create({
mongoUrl: 'mongodb://127.0.0.1:27017/session_store',
ttl: 1000 * 60 * 10
}),
}));
// Auth Middleware
app.use((req, res, next) => {
if (req.url === "/login") return next();
if (req.session.user) {
next();
} else {
res.redirect("/login");
}
});
JSON Web Token (JWT)
JWT is a stateless authentication mechanism. Instead of storing session data on the server, the server generates a signed token containing user information (Payload) and sends it to the client. The client stores this token (usually in LocalStorage) and sends it in the Authorization header.
Implementation:
const jwt = require("jsonwebtoken");
const SECRET_KEY = "super_secret_123";
const AuthService = {
issue(payload, duration) {
return jwt.sign(payload, SECRET_KEY, { expiresIn: duration });
},
validate(token) {
try {
return jwt.verify(token, SECRET_KEY);
} catch (error) {
return null;
}
}
};
module.exports = AuthService;
Server-side Middleware:
app.use((req, res, next) => {
if (req.url === "/login") return next();
const authHeader = req.headers["authorization"];
const token = authHeader && authHeader.split(" ")[1];
if (token) {
const decoded = AuthService.validate(token);
if (decoded) {
// Refresh token logic
const refreshedToken = AuthService.issue({ id: decoded.id }, "1d");
res.header("Authorization", refreshedToken);
next();
} else {
res.status(401).json({ code: -1, msg: "Unauthorized" });
}
} else {
res.status(401).json({ code: -1, msg: "Token missing" });
}
});
Client-side Interceptor (Axios):
import axios from 'axios';
axios.interceptors.request.use(config => {
const storedToken = localStorage.getItem("access_token");
if (storedToken) config.headers.Authorization = `Bearer ${storedToken}`;
return config;
});
axios.interceptors.response.use(response => {
const newToken = response.headers['authorization'];
if (newToken) localStorage.setItem("access_token", newToken);
return response;
}, error => {
if (error.response.status === 401) {
localStorage.clear();
window.location.href = "/login";
}
return Promise.reject(error);
});
4. File Upload Management
Use multer middleware to handle multipart/form-data for file uploads.
Server Setup:
const multer = require('multer');
const uploadMiddleware = multer({ dest: 'public/uploads/' });
router.post('/upload-asset', uploadMiddleware.single('fileResource'), (req, res) => {
console.log(req.file); // Contains file metadata
res.json({ path: `/uploads/${req.file.filename}` });
});
Client Request:
const formData = new FormData();
formData.append('fileResource', selectedFile);
formData.append('userId', '12345');
axios.post('/api/upload-asset', formData, {
headers: { 'Content-Type': 'multipart/form-data' }
});
5. API Documentation with apidoc
apidoc generates documentation from inline code comments.
Install: npm install -g apidoc
Create apidoc.json in the root:
{
"name": "Project API Docs",
"version": "1.0.0",
"description": "Documentation for backend services",
"title": "API Reference"
}
Add comments in your route files:
/**
* @api {get} /user/:id Get User Details
* @apiName GetUserById
* @apiGroup User
*
* @apiParam {Number} id Users unique ID.
*
* @apiSuccess {String} firstname User firstname.
* @apiSuccess {String} lastname User lastname.
*/
app.get('/user/:id', (req, res) => { ... });
Generate docs: apidoc -i src/ -o docs/