user-management
├─config
│ └─config.js
├─db
│ └─db.js
├─models
│ └─UserModel.js
└─routes
│ └─users.js
└─app.js
数据库配置文件 config/config.js:
// config/config.js
module.exports = {
DB_HOST: '127.0.0.1',
DB_PORT: 27017,
DB_NAME: 'demo'
}
数据库链接文件 db/db.js
// db/db.js
const mongoose = require("mongoose");
const { DB_HOST, DB_PORT, DB_NAME } = require("../config/config");
const MONGO_URI = `mongodb://${DB_HOST}:${DB_PORT}/${DB_NAME}`;
// 全局连接 MongoDB(只需调用一次)
module.exports = function connectDB() {
mongoose
.connect(MONGO_URI)
.then(() => console.log("MongoDB connected"))
.catch((err) => {
console.error("MongoDB connection error:", err);
process.exit(1); // 退出进程(可选)
});
// 连接失败回调
mongoose.connection.on("error", (err) => {
console.error("MongoDB connection error:", err);
});
// 连接成功回调
mongoose.connection.on("close", () => {
console.log("MongoDB connection closed");
});
};
用户模型文件 models/UserModel.js
const mongoose = require('mongoose');
const UserSchema = new mongoose.Schema({
username: {
type: String,
required: true,
unique: true,
},
password: {
type: String,
required: false,
default: '123456',
}
})
const UserModel = mongoose.model('User', UserSchema)
module.exports = UserModel
用户路由文件 routes/users.js
const express = require('express');
const ResponseModel = require("../models/ResponseModel");
const UserModel = require("../models/UserModel");
const router = express.Router();
/**
* get all users with pagination and fuzzy search
* query params:
* - page (default 1)
* - limit (default 10)
* - username (optional, fuzzy search)
* GET /users?username=adm&page=1&limit=5
*/
router.get('/', async function (req, res, next) {
try {
// 获取分页参数,设置默认值
const page = parseInt(req.query.page) || 1;
const limit = parseInt(req.query.limit) || 10;
const skip = (page - 1) * limit;
// 获取模糊查询参数
const { username } = req.query;
// 构建查询条件
const query = {};
if (username) {
query.username = { $regex: username, $options: 'i' }; // i表示不区分大小写
}
// 查询数据(带分页和模糊查询)
const data = await UserModel.find(query)
.select('username')
.skip(skip)
.limit(limit);
// 获取总记录数用于计算总页数
const total = await UserModel.countDocuments(query);
const totalPages = Math.ceil(total / limit);
// 返回分页数据
res.json(ResponseModel.success("获取所有用户成功!", {
data,
pagination: {
currentPage: page,
totalPages,
totalItems: total,
itemsPerPage: limit
}
}));
} catch (err) {
console.log("获取所有用户失败", err);
res.json(ResponseModel.error(err.message));
}
});
/**
* get detail of a user by id
*/
router.get('/:id', async function (req, res, next) {
const { id } = req.params;
if(!id) return res.json(ResponseModel.error('请输入用户ID'));
try {
const data = await UserModel.findOne({_id: id}) // 注意mongodb的集合中_id字段有下划线
if(!data) return res.json(ResponseModel.error('该ID无效,用户不存在'));
return res.json(ResponseModel.success("获取用户详情成功!", data));
} catch (err) {
console.log("获取用户详情失败", err);
return res.json(ResponseModel.error(err.message));
}
});
/**
* create/register a user
*/
router.post('/', async function (req, res, next) {
const {username, password} = req.body;
if (!username) {
return ResponseModel.error('创建失败,缺少用户名或密码')
}
try {
const data = await UserModel.create({
username, password
});
return res.json(ResponseModel.success("创建新用户成功!", data));
} catch (err) {
console.log("Error creating user:", err);
if (err.code === 11000) {
return res.json(ResponseModel.error('创建失败,用户名重复'));
} else {
return res.json(ResponseModel.error(err.message));
}
}
});
/**
* update a user
*/
router.put('/:id', async function (req, res, next) {
const { id } = req.params;
const { username, password } = req.body;
// 检查必填字段
if (!id) return res.json(ResponseModel.error('请输入用户ID'));
if (!username && !password) {
return res.json(ResponseModel.error('至少提供一个更新字段(username 或 password)'));
}
try {
// 构建更新对象(只更新提供的字段)
const updateData = {};
if (username) updateData.username = username;
if (password) updateData.password = password;
// 执行更新
const updatedUser = await UserModel.findByIdAndUpdate(
id,
updateData,
{ new: true } // 返回更新后的文档
);
if (!updatedUser) {
return res.json(ResponseModel.error('用户不存在'));
}
return res.json(ResponseModel.success('更新用户成功', updatedUser));
} catch (err) {
console.log("更新用户失败", err);
if (err.code === 11000) {
return res.json(ResponseModel.error('更新失败,用户名已存在'));
}
return res.json(ResponseModel.error(err.message));
}
});
/**
* delete a user
*/
router.delete('/:id', async function (req, res, next) {
const { id } = req.params;
if(!id) return res.json(ResponseModel.error('请输入用户ID'));
try {
const data = await UserModel.deleteOne({_id: id}) // 注意mongodb的集合中_id字段有下划线
if (data.deletedCount === 0) { // 注意检查deletedCount
return res.json(ResponseModel.error('用户不存在'));
}
return res.json(ResponseModel.success('删除用户成功'));
} catch (err) {
console.log("删除用户失败", err);
return res.json(ResponseModel.error(err.message));
}
});
module.exports = router;
核心文件 app.js
const express = require('express');
const path = require('path');
const cookieParser = require('cookie-parser');
const logger = require('morgan');
const connectDB = require('./db/db');
const moviesRouter = require('./routes/movies');
const usersRouter = require('./routes/users');
const app = express();
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
connectDB()
app.use('/movies', moviesRouter);
app.use('/users', usersRouter);
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server is running: http://localhost:${PORT}`);
});
module.exports = app;
文件根目录下启动app.js
node app.js