Node Express MongoDB 用户管理 CRUD 增删查改

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值