node学习笔记(2)
准备开始
启程helloworld
- 安装
npm i express -S
- 1:引入express第三方对象
- 2:构建一个服务器对象
- 3:开启服务器监听端口
- 4:处理响应
- 在express中,保留了原生http的相关属性和函数
app.use([path,] callback [, callback…])
将指定的一个或多个中间件函数装入指定的路径:当请求的路径与参数中路径匹配时,将执行中间件函数。
- app.use(fn)是请求与响应中执行的一件事,和代码书写顺序有关
- next()的调用是放行到下一件事的开关。
- 如果全是next(),最终没有end页面数据,框架帮我们处理了status:404
- app.use(fn)是任何请求都会触发执行的
- 用户/abc/def的请求
- 选择性调用app.use(’/abc’,fn)的中间件
- 但是内部req.url则去除了/abc这个目录
app.use app.get app.post区别
references:
app.use(path,callback)中的callback既可以是router对象又可以是函数
app.get(path,callback)中的callback只能是函数
给app.get(app.post、app.put同理)赋个路由对象是不行的,其实,可以将app.get()看作app.use的特定请求(get)的简要写法
var express = require('express');
var app = express();
app.get('/hello',function(req,res,next){
res.send('hello test2');
});
等价于
var express = require('express');
var app = express();
var router = express.Router();
router.get('/', function(req, res, next) {
res.send('hello world!');
});
app.use('/hello',router);
路由规则是app.use(path,router)定义的,router代表一个由express.Router()创建的对象,在路由对象中可定义多个路由规则。可是如果我们的路由只有一条规则时,可直接接一个回调作为简写,也可直接使用app.get或app.post方法。即
当一个路径有多个匹配规则时,使用app.use,否则使用相应的app.method(get、post)
中间件类别
中间件就是请求和响应中间的一个行为
- 应用级中间件
app.use(fn)
- 路由级中间件
- 1:获取路径级中间件
- 2:配置路由
- 3:加入到应用程序控制中
app.use(router);
- 内置中间件
- 处理一些静态资源文件的返回(设置将某个目录下的资源文件向外暴露)
- 当url匹配上我设置的目录下的子文件后,自动返回该文件
- 加入到应用程序控制中
app.use(内置中间件);
- 处理一些静态资源文件的返回(设置将某个目录下的资源文件向外暴露)
- 第三方中间件
- 更方便的处理cookie/session,简易的解析post请求体数据
- 在npm上下载并使用
- 加入到应用程序控制中
app.use(第三方中间件);
- 错误处理中间件(优化用户体验)
- 在express中统一处理错误
next(err)
然后最后用app.use((err,req,res,next)=>{})
统一处理 - 用res.send res.end res.render响应错误提示页面。
- 在express中统一处理错误
路由中间件
- 一个请求进来(总网线),分发到各自不同的处理(分多根网线给其他人)
- 分流
- 后端路由
- (请求方式 + URL = 判断依据)(分流的判断依据) -> 做不同的处理(分流后的行为)
- 使用步骤
- 1:获取路由中间件对象
let router = express.Router();
- 2:配置路由规则
router.请求方式(URL,fn事)
- fn中参数有req,res,next
- 3:将router加入到应用
app.use(router)
- 1:获取路由中间件对象
路由
res扩展函数
res.download('./xxx.txt') // 下载文件:基于服务器回写的content-Disposition等头信息
res.json({}) // 响应json对象
res.jsonp(数据) // 配合jsonp 要求客户端请求的时候也是jsonp的方式, 并且callback=xxx
res.redirect() // 重定向 301是永久重定向, 302临时重定向
res.send() // 发送字符串数据自动加content-type
res.sendFile() // 显示一个文件
res.sendStatus() // 响应状态码
注:
header中Content-Disposition的作用与使用方法
Content-disposition 是 MIME 协议的扩展,MIME 协议指示 MIME 用户代理如何显示附加的文件。Content-disposition其实可以控制用户请求所得的内容存为一个文件的时候提供一个默认的文件名,文件直接在浏览器上显示或者在访问时弹出文件下载对话框。
模板渲染
使用art-template模板引擎
- 下载express-art-template art-template
- app.js中配置
- 注册一个模板引擎
app.engine('.html',express-art-template);
- 设置默认渲染引擎
app.set('view engine','.html');
- 设置默认渲染引擎
- res.render(文件名,数据对象);
- express这套使用,默认在当前app.js同级的views目录查找
- 注册一个模板引擎
内置中间件(处理静态资源)
- 1: 创建对象
let static = express.static('./public');
- 2: 配置到中间件中
app.use(static);
第三方中间件(post请求体的获取)
- 原生的:
req.on('data',data=>{ data.toString();})
const bodyParser = require('body-parser');
// 解析键值对application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }));
// 不用扩展的库来解析键值对,而使用node内置核心对象querystring来解析键值对
// 解析application/json
app.use(bodyParser.json());
服务端处理错误和404页面找不到
- 404页面响应
router.all('*',()=>{} )
- 触发错误
- next(err);
- 处理错误 app.use( 4参数函数 )
nodemon
- 修改代码自动重启
- 安装全局命令行工具
npm i -g nodemon
- 进入到指定目录命令行
nodemon ./xxx.js
- 手动触发重启,在命令行输入 rs回车
接下来进行数据的持久化:连接数据库
MongoDB
- 一个数据库对应多个集合
- 一个集合对应多个文档对象
- 在mongo中不论是db还是集合,你都无需去创建他
- 直接就当他已经存在,直接Use来使用
- use db名称;
- 接着会被切换到该db中
db.要创建的集合名称.save({})
;这样集合就被创建了
- use db名称;
- 1:启动服务器
mongod --dbpath "D:/mongodb/db"
// 目录一定要存在自己创建随便名称‘- 尽量设置在非系统盘
C盘生成目录是需要权限的
- 尽量设置在非系统盘
- 如果看到
waiting for connections on port 27017
说明服务已经启动
- 客户端连接服务器另开一个命令行
mongo
默认连接的是test数据库
- 查询有哪些数据库
- 查询数据库:
show dbs;
- 切换数据库:
use 数据库名;
- 查询数据库:
- 查询当前db下有哪些集合
show collections;
- 查询数据:
db.集合名.find();
//查询出来的是文档对象 documentdb.users.find();
- 添加数据:
db.集合名.save(对象)
//mongo默认会给我们加入_id作为该文档对象的唯一标识db.users.save({contry:'中国',name:'小明',score:77});
- 删除数据:
db.集合名.remove(条件对象);
//条件匹配就会被删除db.users.remove({name:'小明'});
- 如果给定一个空对像,会匹配全部
- 更新数据:
db.集合名.update({匹配条件对象},{$set:{修改后的对象}});
db.users.update({name:'小明'},{$set:{contry:'印度'}});;
条件查询
练习:
查询姓名为小明的学生
db.users.find({name:'小明'});; 查询英语成绩大于90分的同学
db.users.find({score:{$gt:90}}); //查找成绩大于90分$gt
//$lt小于
查询数学成绩不等于88的同学
db.users.find({score:{$ne:88}}); 查询总分大于200分的所有同学
db.users.find({score:{$gt:200}});
分页
db.users.find().skip(3).limit(3);
- db.集合名称.find().跳到3.显示3条
+ limit 0,3
排序
db.users.find().sort({key:排序方式});
db.users.find().sort({'score':1});
//正数代表升序,负数代表降序
模糊匹配
db.users.find({name:{$regex:'小'}});
db.users.find({name:{$regex:'明'}});
聚合函数
- 需要求当前集合的记录数:
db.users.find().count();
- 求最大值
-求整个集合的总成绩
+ db.集合名.聚合({ 组的划分规则{_id:‘1’,显示内容:{score’}} })- 求所有人的平均分
db.users.aggregate({$group:{_id:'1',sumscore:{$avg:'$score' } }});
- 求按国家分组,求所有国家的总分
db.users.aggregate({$group:{_id:'$contry',sumScore:{$sum:'$score'}}});
- 求所有人的平均分
- 添加基础数据:
db.users.save({contry:‘中国’,name:‘小明’,score:77});
db.users.save({contry:‘中国’,name:‘小红’,score:88});
db.users.save({contry:‘中国’,name:‘小张’,score:99});
db.users.save({contry:‘美国’,name:‘jack’,score:45});
db.users.save({contry:‘美国’,name:‘rose’,score:67});
db.users.save({contry:‘美国’,name:‘mick’,score:89});
解决32位异常
mongod --dbpath=“路径” --journal --storageEngine=mmapv1
常见错误
references:
Error: ENOENT: no such file or directory, uv_cwd错误
一般此为文件指向发生了错误;
解决方法:重新开一个终端
。
配置https
- 公钥 公开的加密方式
- 私钥 存在服务器的唯一解公钥加密的方式
- 签名 确保数据的一致性
- 证书 确保当前发送数据单位可信
扩展知识(使用mongodb实现附近的人)
// 创建索引
db.test.createIndex({"sp":"2dsphere"});
db.test.insert({name:"A",sp:{type:"Point",coordinates:[105.754,41.689]} });
db.test.insert({name:"B",sp:{type:"Point",coordinates:[105.304,41.783]} });
db.test.insert({name:"C",sp:{type:"Point",coordinates:[105.084,41.389]} });
db.test.insert({name:"D",sp:{type:"Point",coordinates:[105.831,41.285]} });
db.test.insert({name:"E",sp:{type:"Point",coordinates:[106.128,42.086]} });
db.test.insert({name:"F",sp:{type:"Point",coordinates:[105.431,42.009]} });
db.test.insert({name:"G",sp:{type:"Point",coordinates:[104.705,41.921]} });
查找附近的人
db.test.find(
{
sp:
{
$nearSphere :
{
$geometry: {
type: "Point",
coordinates:[105.304,41.783]
},
$minDistance: 25000,
$maxDistance: 40000
}
}
}
)
离我最近
db.test.aggregate({
$geoNear: {
near: { type: "Point", coordinates:[105.304,41.783]},
distanceField: "dist.calculated",
spherical:true,
maxDistance: 40000
}
})
- 经纬度查询网站
http://www.gpsspg.com/maps.htm
数据库知识
references:
数据库索引
索引作用
使查询数据效率快
索引分类
- 聚集索引(主键索引):在数据库里面,所有行数都会按照主键索引进行排序。
- 非聚集索引:就是给普通字段加上索引。
- 联合索引:就是好几个字段组成的索引,称为联合索引。注:联合索引遵从最左前缀原则
不走索引
- Like这种就是%在前面的不走索引,在后面的走索引
- 用索引列进行计算的,不走索引
- 对索引列用函数了,不走索引
- 索引列用了!= 不走索引
数据库聚合
往往是各种聚合函数的使用:比如count
sum
等。
来源:CSDN
作者:LynnWonderLu
链接:https://blog.csdn.net/lynnwonder6/article/details/103484770