Skip to content

youkei-zzz/Natours

Repository files navigation

Mongoing 文档

🌟①. 官方文档

✨②. 官方文档

0. 永远不要用 update 的方法更新密码相关的东西

绕过中间件的情况

1.query、params、body

1). req.query为查询参数对 ? 后面的 & 连接的所有参数名称。
2). req.body是用在post请求当中的
3). req.prams是对应于后端代码中 :xxx 的部分 ?的前面。

2.数组方法

1). 如果想删除tableData集合中的name属性,需要用forEach遍历tableData集合,然后在遍历过程中,直接调用 delete item.name ,就可以把集合中的name属性删除掉

3.JS中的其它方法

1). JSON.parse()用于从一个字符串中解析出json对象。
2). JSON.stringify()用于将一个json对象解析成字符串形式

4.使用优化

//build query
const query = Tour.find(queryObj);
// 2.excute query
const tours = await query;
// 这样可以不用等待 find查询并返回文档的过程使得分页排序这些卡住,可以加快速度

5. module.exports与exports.xxx

👉 CSDN

6. $project

将仅包含指定字段的文档传递到管道中的下一阶段。指定的字段可以是输入文档中的现有字段,也可以是新计算的字段

语法	                描述
<字段> : <1 或真>	指定包含字段。
_id : <0 或假>	    指定_id字段的抑制。
<字段>:<表达式>	    添加新字段或重置现有字段的值。

7. MongoDB中间件 | isModified() 函数

👉 CSDN

// 1. 只能用 function  2. doc指向正在保存的文档内容 ,在.create()和.save()方法之前会被调用
tourSchema.post("save", function (doc,next) {
	console.log(doc); // 输出执行post的文档信息
	if(!this.isModified('')){
		// .....
		// isModified() : 如果文档被改了返回true 否则为false
		//  isModified('xxx') 如果给出指定的字段 则会检查给定字段的或者是包含这个字段的全路径是否被改变 改变了返回true 否则返回false
	}
	next();
});
--------------------------------------------------------------

// 注意此处的 find 在执行 find时 有效 但是 在执行 findOne() findById() findOneAndUpdate() 时 不会进入这个钩子
tourSchema.pre('find', function (next) {
	.....
	next();
});

tourSchema.pre('findOne', function (next) {
	.....
});
....  // 如此 太麻烦 可以用正则表达式 指定。example:  tourSchema.pre(/^find/, function (next) {...});

//  Aggregation MiddleWare
tourSchema.pre('aggregate', function (next) {
	// 指向当前的aggregate(而且是一个数组 可以用 unshift()来增加 pipeline中的内容 以此来进一步分类、分组或者是过滤...)
		console.log(this);
/*
	Aggregate {
  _pipeline: [
    { '$unwind': '$startDates' },
    { '$match': [Object] },
    { '$group': [Object] },
    { '$addFields': [Object] },
    { '$project': [Object] },
    { '$sort': [Object] },
    { '$limit': 6 }
  ],
  _model: Model { Tour },
  options: {}
}
*/

});
------------------------
2.post中间件回调的参数(使用arguments查看
)
// 有时候参数不对 会使这个钩子 无法被识别
// 有三个,默认传入的第一个是查询出来的文档内容,第二个是若有错误的error信息,第三个是next函数

8. 处理错误路径(app.js中)

app.use('...', xxx);

// 位置要放在最后面 不然都被拦截了
// 如果之前的路由没匹配上则说明这个 url有问题,all表明无论get post patch.... 只要没进入上面正确的路由那么都会被这个匹配,进入这个处理
app.all('*', (req, res, next) => {
	res.status(404).json({
		status: 'fail',
		message: `can't find ${req.originalUrl}`,
	});
});

9. Error.captureStack() 大概意思

👉 CSDN


10. 关于异步的封装(避免写很多重复的try...catch)

/*  

1.express的路由里抛出异常后,全局中间件没办法捕获,需要在所有的路由函数里写try catch,这坑爹的逻辑让人每次都要多写n行代码  所以单独提取一个catchAsync.js文件 导入其他文件中 使用该方法

2.参照 http://www.qb5200.com/article/360363.html 

*/

// 返回一个匿名函数给 const定义的那个常量,这个返回的函数执行传入catchAsync的函数fn,并调用catch捕获异常
const catchAsync = fn => {
	return (req, res, next) => {
		fn(req, res, next).catch(next);
	};
};
exports.catchAsync = catchAsync;

11. 关于MongoDB 中的validate(验证器)何时生效

//
	passwordConfirm: {
		type: String,
		required: [true, 'Please confirm your password!'],
		// 不能使用 ()=> 因为 this 无法指向 创建的文档
		// 这个只在执行 save 或者是 create 操作时有效!!!!!
		validate: {
			validator: function (el) {
				return el === this.password;
			},
		},
	},

12. Node内置的 promisify

// 导入方法
const { promisify } = require('util');
// Node.js 内置的 util 模块有一个 promisify() 方法,该方法将基于回调的函数转换为基于 Promise 的函数。这使您可以将 Promise 链和 async/await 与基于回调的 API 结合使用。

// 例如 :
const fs = require('fs')
const util = require('util')// 将 fs.readFile() 转换为一个接受相同参数但返回 Promise 的函数。
const readFile = util.promisify(fs.readFile)// 现在可以将 readFile() 与 await 一起使用!
const buf = await readFile('./package.json')const obj = JSON.parse(buf.toString('utf8'))
console.log(obj.name) // 'Example'

12. crypto 的大概用法

注意:还有一个第三方包 bcrypt

const resetToken = crypto.randomBytes(32).toString('hex');
// resetToken 得出随机的一个字符串  createHash指出要用什么加密算法  update 的参数是需要加密的数据。 update() 可以多次被调用,多次调用只是简单的把要加密的结果拼接起来。digest指明用什么形式输出这个字符串
this.passwordResetTOKEN = crypto.createHash('sha256').update(resetToken).digest('hex');

13. res.cookie(name, value, [options])

// Expires – 过期时间。指定cookie的生命期。具体是值是过期日期。如果想让cookie的存在期限超过当前浏览器会话时间,就必须使用这个属性。当过了到期日期时,浏览器就可以删除cookie文件,没有任何影响。

// Path – 路径。指定与cookie关联的WEB页。值可以是一个目录,或者是一个路径。如果/head/index.html 建立了一个cookie,那么在/head/目录里的所有页面,以及该目录下面任何子目录里的页面都可以访问这个cookie。这就是说,在/head/stories/articles 里的任何页面都可以访问/head/index.html建立的cookie。但是,如果/zdnn/ 需要访问/head/index.html设置的cookes,该怎么办?这时,我们要把cookies的path属性设置成“/”。在指定路径的时候,凡是来自同一服务器,URL里有相同路径的所有WEB页面都可以共享cookies。现在看另一个例子:如果想让 /head/filters/ 和/head/stories/共享cookies,就要把path设成“/head”。

// Domain – 域。指定关联的WEB服务器或域。值是域名,比如goaler.com。这是对path路径属性的一个延伸。如果我们想让dev.mycompany.com 能够访问bbs.mycompany.com设置的cookies,该怎么办? 我们可以把domain属性设置成“mycompany.com”,并把path属性设置成“/”。FYI:不能把cookies域属性设置成与设置它的服务器的所在域不同的值。

// Secure – 安全。指定cookie的值通过网络如何在用户和WEB服务器之间传递。这个属性的值或者是“secure”,或者为空。缺省情况下,该属性为空,也就是使用不安全的HTTP连接传递数据。如果一个 cookie 标记为secure,那么,它与WEB服务器之间就通过HTTPS或者其它安全协议传递数据。不过,设置了secure属性不代表其他人不能看到你机器本地保存的cookie。换句话说,把cookie设置为secure,只保证cookie与WEB服务器之间的数据传输过程加密,而保存在本地的cookie文件并不加密。如果想让本地cookie也加密,得自己加密数据。

设置 cookie name 值为 value, 接受字符串参数或者 JSON 对象。 path 属性默认为 "/".

res.cookie('name', 'tobi', { domain: '.example.com', path: '/admin', secure: true });

res.cookie('rememberme', '1', { expires: new Date(Date.now() + 900000), httpOnly: true });

maxAge 属性是一个便利的设置"expires",它是一个从当前时间算起的毫秒。 下面的代码和上一个例子中的第二行是同样的作用。

res.cookie('rememberme', '1', { maxAge: 900000, httpOnly: true });

可以传一个序列化的 JSON 对象作为参数, 它会自动被 bodyParser() 中间件解析。

res.cookie('cart', { items: [1, 2, 3] });
res.cookie('cart', { items: [1, 2, 3] }, { maxAge: 900000 });

这个方法也支持签名的 cookies。 只需要简单的传递 signed 参数。 res.cookie() 会使用通过 express.cookieParser(secret) 传 入的 secret 来签名这个值

res.cookie('name', 'tobi', { signed: true });

稍后你就可以通过 req.signedCookie 对象访问到这个值。

14. MongoDB 数据库模型关系

15. 索引可以加快搜索速度

db.collection.createIndex({ 'a.loc': 1, 'a.qty': 1 }, { unique: true }); // MongoDB 将对索引键值的组合强制实施唯一性。
// 因此我们可以利用这一特性对 每个用户限制只能评论一次

👉 CSDN(操作) 👉 Compound Index


16. Aggregate 聚合管道

1.$group:	// 按指定的标识符表达式对输入文档进行分组,并将累加器表达式(如果指定)应用于每个组。使用所有输入文档,并为每个不同的组输出一个文档。输出文档仅包含标识符字段和累积字段(如果已指定)。按某个指定的表达式对文档进行分组,并将每个不同分组的文档输出到下一阶段。输出文档包含一个_id字段,该字段包含按键的不同组。输出文档还可以包含计算字段,这些字段保存按$group_id字段分组的某个累加器表达式的值。$group不对其输出文档进行排序。

👉 $group

2.$set: // 运算符将字段的值替换为指定的值。

👉 $set

3.$geoNear://按距指定点最近到最远的顺序输出文档。

👉 $geoNear

4.$geoWithin: //选择具有完全存在于指定形状内的地理空间数据的文档。
	可用的形状运算符有:
	$box
	$polygon
	$center //(定义一个圆)
	$centerSphere //(在球体上定义一个圆)。为地理空间使用球面几何的查询。该查询返回圆圈范围内的文档。

// 如果您使用经度和纬度,请按 的顺序指定坐标longitude, latitude。


{
   <location field>: {
      $geoWithin: { $centerSphere: [ [ <x>, <y> ], <radius> ] }
   }
}

例如:
db.places.find( {
  loc: { $geoWithin: { $centerSphere: [ [ -88, 30 ], 10/3963.2 ] } }
} )

👉 $geoWithin

👉 运算符 : $centerSphere

17. 路径

// 在图片和css文件加载的时候路径很容易出错 从而导致 加载失败
src="/xxxx/xxx"  src="xxxx/xxx  并不一样。
// 有斜线的从根路径开始
// 没有斜线的的是从 当前网站的路径 开始找css文件 或者是图片

18. 虚拟填充

Query.populate(path, [select], [model], [match], [options])

select: populate 的文档中选择返回的字段
path:指定要查询的表
fields:填充的内容
Model: 可选,指定关联字段的 model,如果没有指定就会使用Schema的ref
Object:可选,指定附加的其他查询选项,如排序以及条数限制等等。

// 请记住,默认情况下,虚拟虚拟不包括在输出中。如果您希望在使用 Express 的 res.json() 函数 或 等函数时显示填充虚拟虚拟,请在架构和选项上设置该选项。toJSON()toObject

const authorSchema = new Schema({ 字段... }, {
  toJSON: { virtuals: true }, // So `res.json()` and other `JSON.stringify()` functions include virtuals
  toObject: { virtuals: true } // So `console.log()` and other functions that use `toObject()` include virtuals
});

👉 填充

19. Npm 安装命令

npm install moduleName
npm install --global moduleName
npm install --save moduleName
npm install --save-dev moduleName

npm

20. Pug 变量 | 👉 文档

1) app.locals

该对象的属性是应用程序中的局部变量,并且可以在使用 res.render.app.locals 呈现的模板中使用 设置后,属性的值将在应用程序的整个生命周期中持续存在,这与仅在请求的生存期内有效的 res.locals 属性形成对比。app.locals 您可以在应用程序中呈现的模板中访问局部变量。这对于向模板以及应用程序级数据提供帮助器函数非常有用。局部变量可通过在中间件中使用(请参阅 req.app req.app.locals)

2).res.locals

app.use(function (req, res, next) {
  // Make `user` and `authenticated` available in templates
  res.locals.user = req.user
  res.locals.authenticated = !req.user.anonymous
  next()
})

使用此属性可以设置在使用 res.render 呈现的模板中可访问的变量。设置为 上的变量在单个请求-响应周期内可用,并且不会在请求之间共享。res.locals 为了保留局部变量以便在请求之间的模板呈现中使用,请改用 app.locals。 此属性可用于向应用程序中呈现的模板公开请求级信息,如请求路径名、经过身份验证的用户、用户设置等。

21. XMLHttpRequest setHeaders 参数

// 设置响应头
ajax.setRequestHeader('Content-Type', 'application/json;charset=UTF-8');
// 发送json对象
ajax.send(JSON.stringify(data));
ajax.onreadystatechange = function (){
	if (ajax.readyState === 4){
		if (ajax.status === 200 && ajax.status < 400){
			...
		}else{
			....
		}
	}
}

22. Sharp 高性能裁剪图片

23. XMLHttpRequest发送表单 |✨ 👉 示例

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published