# nodejs服务模板 **Repository Path**: rowrey/nodejs-service-template ## Basic Information - **Project Name**: nodejs服务模板 - **Description**: nodejs服务端模板 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2024-05-15 - **Last Updated**: 2025-07-16 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README npm install koa koa-json koa-bodyparser @koa/router @koa/cors mongoose # 快速配置项目 - npm install -g koa-generator koa2 /目录 && ce /目录 # 配置路由等 - npm install @koa/router ```javascript const router = require('@koa/router')(); const json = require('koa-json') // 用于将http响应的数据转换为json格式 const bodyParser = require('koa-bodyparser') // 解析http请求的消息体 const cors = require('@koa/cors') // 允许跨域 // 使用路由 router.get('/', async (ctx) => {}); // 注意顺序 不让post请求拿不到body参数 app.use(bodyParser()) app.use(cors()) app.use(json()) app.use(router.routes()).use(router.allowedMethods()) ``` # 配置模板 - npm install koa-static ```javascript // 1. 引入koa-art-template const render = require('koa-art-template'); // 2. 配置art-template模板引擎 render(app, { root: path.join(__dirname, 'views'), // 视图的位置 extname: '.html', // 后缀名 debug: process.env.NODE_ENV !== 'production' // 是否开启调试模式 }); ``` # 配置静态资源 - npm install koa-static ```javascript const static = require('koa-static') // 静态资源 app.use(static(__dirname + '/views/static')) ``` # 设置cookie ```javascript ctx.cookies.set('userInfo', Buffer.from(JSON.stringify(ctx.state)).toString('base64'), { maxAge: 1000 * 60 * 5, // 过期时间 domain: '.xxx.com' // 二级域名共享cookie }) ``` # 获取cookie ```javascript Buffer.from(ctx.cookies.get('userInfo'), 'base64').toString() ``` # session使用 - npm install koa-session ```javascript const session = require('koa-session') app.keys = ['travel keys'] const CONFIG = { key: 'koa.somename', maxAge: 1000 * 60 * 60 * 24, rolling: true, /** 每次请求重新设置时间*/ renew: false, /** 请求时在快要过期时重新设置cookie*/ secure: false /* 是否只允许htts里面设置cookie */ } app.use(session(CONFIG, app)) // 设置session ctx.session.username = 'xx' // 获取 ctx.session.username ``` # 配置公共中间件 ```javascript // 我们需要在每个路由的render中都渲染一个公共的数据 // 写一个中间件配置公共信息 app.use(async (ctx, next) => { // 匹配路由之前 可以进行权限判断等操作 // 公共的数据要放在ctx.state中 ctx.state = { userinfo: '李四', age: '18', } await next() // 错误处理 找不到路由时 if (ctx.status === 404) { ctx.body = '404:页面没有找到' } }) ``` # mongo 7.0之后 连接mongo需要下载mongosh 配置环境变量 - D:\mongosh-2.1.1-win32-x64\bin cmd mongosh - C:\Program Files\MongoDB\Server\7.0\bin - 表操作 - 查看表 show dbs - 新建/使用表 use dbname - 新建表需要插入数据才会显示 db.user.insert({'':''}) - 查看集合 show collections - 删除集合 db.user.drop() - 删除数据库,删除当前所在的数据库 db.dropDatabase(); - 查看所有记录 db.user.find(); ```javascript // $gt:大于 // $lt:小于 // $gte:大于等于 // $lte:小于等于 // $ne:不等于 // $in:包含于 // $nin:不包含于 // $regex:正则表达式匹配 db.user.find({ username: { $in: ['Luolei']}}) // 更新 // 1.findOneAndUpdate()更新符合条件的第一条文档 name为张三的更新为李四,只更新第一条 db.user.findOneAndUpdate({ name: '张三' }, { name: '李四' }) // 2.updateMany()更新所有符合条件的文档 使用updateMany更新多条文档 db.user.updateMany({ name: '张三' }, { name: '李四' }) // 3.updateMany()深度更新字段 // 假如name是个嵌套对象字段,比如: // {name:{a:{b:{c:'张三'}}}} // //使用.和$set来深度更新 db.user.updateMany({ 'name.a.b.c': '张三' }, { $set: { 'name.a.b.c': '李四' } }) // 批量添加 db.user.create([{}]) // 删除 db.user.deleteMany({age:{$gt:10}}) // 查询name 中包含mongo 的数据模糊查询用于搜索 db.user.find({name: /mongo/}); // 查询name 中以mongo 开头的 db.user.find({name: /^mongo/}); // 升序: db.user.find().sort({age: 1}); // 降序: db.user.find().sort({age: -1}); // 可用于分页,limit 是pageSize,skip 是(page-1)*pageSize // 查询前5 条数据 db.user.find().limit(5); // 查询10 条以后的数据 db.user.find().skip(10); // 查询在5-10 之间的数据 db.user.find().limit(10).skip(5); // or 与查询 db.user.find({$or: [{age: 22}, {age: 25}]}); // 查询某个结果集的记录条数 统计数量 db.user.find({age: {$gte: 25}}).count(); // 如果要返回限制之后的记录数量,要使用count(true)或者count(非0) db.users.find().skip(10).limit(5).count(true); // 修改数据 db.users.update({"name":"小明"},{$set:{"age":16}}); // 批量修改multi: true db.student.update({"sex":"男"},{$set:{"age":33}},{multi: true}); // 完整替换,不出现$set 关键字了: 注意 db.users.update({"name":"小明"},{"name":"大明","age":16}); // 删除数据 db.users.remove({age: 132}); ``` # 提高数据库查询速度 查询userame时 给userame创建索引 - 创建索引的命令 db.user.ensureIndex({"userame":1}) - 获取当前集合的索引: db.user.getIndexes() - 删除索引的命令是: db.user.dropIndex({"username":1}) 创建复合索引 - 数字1 表示username 键的索引按升序存储,-1 表示age 键的索引按照降序方式存储。 db.user.ensureIndex({"username":1, "age":-1}) 查询具体的执行时间 - explain executionStats db.tablename.find().explain("executionStats") 唯一索引 - 创建唯一索引后,userid不能插入相同的数据 db.user.ensureIndex({"userid":1},{"unique":true}) # MongoDB 的高级查询aggregate 聚合管道 - $project 增加、删除、重命名字段 - $match 条件匹配。只满足条件的文档才能进入下一阶段 - $limit 限制结果的数量 - $skip 跳过文档的数量 - $sort 条件排序。 - $group 条件组合结果统计 - $lookup 用以引入其它集合的数据(表关联查询) 常用表达式操作 - $addToSet 将文档指定字段的值去重 - $max 文档指定字段的最大值 - $min 文档指定字段的最小值 - $sum 文档指定字段求和 - $avg 文档指定字段求平均 - $gt 大于给定值 - $lt 小于给定值 - $eq 等于给定值 ```javascript // 多个表查询 创建多个$lookup 关联主表就行 db.order.aggregate([ { $lookup: { from: "order_item", // 副表 localField: "order_id", // 主表关联字段 foreignField: "order_id", // 副表关联字段 as: "items" // 返回集合键值 } }, { $project:{ trade_no:1, all_price:1,items:1 } // 过滤字段 只显示这几个字段 }, { $match:{"all_price":{$gte:90}} // 查找all_price 大于等于90 }, { $sort:{"all_price":-1} // 按照all_price 降序 }, ]) ``` # 数据库备份 - mongodb数据库导出备份语法: mongodump -h dbhost -d dbname -o dbdirectory 参数说明: -h: MongDB所在服务器地址,例如:127.0.0.1,当然也可以指定端口号:127.0.0.1:27017 -d: 需要备份的数据库实例,例如:test -o: 备份的数据存放位置,例如:/home/mongodump/,当然该目录需要提前建立,这个目录里面存放该数据库实例的备份数据。 - mongodb数据库恢复导入语法: mongorestore -h dbhost -d dbname dbdirectory 参数或名: -h: MongoDB所在服务器地址 -d: 需要恢复的数据库实例,例如:test,当然这个名称也可以和备份时候的不一样,比如test2 --drop: 恢复的时候,先删除当前数据,然后恢复备份的数据。就是说,恢复后,备份后添加修改的数据都会被删除,慎用! - mongodb数据库有用户名密码认证的参考下面命令 mongodump -h 127.0.0.1:27017 -d test -u test -p testpwd -o D:\dump mongorestore -h 127.0.0.1:27017 -d test -c order --dir d:\dump\test\test.bson -u test -p testpwd # 定义Schema 的时候指定创建索引 ```javascript var DeviceSchema = new mongoose.Schema({ sn: { type: Number, // 唯一索引 unique: true }, name: { type: String, // 普通索引 index: true } }) ``` # 校验参数 - 内置 required : 表示这个数据必须传入 max: 用于Number 类型数据,最大值 min: 用于Number 类型数据,最小值 enum:枚举类型,要求数据必须满足枚举值enum: ['0', '1', '2'] match:增加的数据必须符合match(正则)的规则 maxlength:最大值 minlength:最小值 - 自定义 validate ```javascript phone:{ type:Number, match: /^\d{11}$/ }, desc: { type: String, // 自定义的验证器,如果通过验证返回true,没有通过则返回false validate: function(desc) { return desc.length >= 10; } } ```