Node基础知识整理
为啥要学Node?
Node 对于前端来讲 是进阶高级前端开发工程师必备的技能。
Node.js 是什么?
1,node不是一门语言,不是库,也不是框架,而是一个建立在谷歌V8引擎的用来解析和执行js代码的运行环境。
2,node可以让js脱离浏览器来运行了
浏览器中的JS:
ECMAScript
if
var
function
object
array
BOM
DOM
…
node中的JS:
ECMAScript
没有BOM DOM
在node这个js执行环境中为JS提供了一些服务器级别的API,例如:
文件读写fs,网络服务构建,网络通信,http服务器等
3,特点: 应用数据驱动 非阻塞I/O模型(异步操作) 轻量级 高效
4,node.js的包的生态系统----npm ,是世界上最大的开源库生态系统
绝大多数的js相关的包 都存放在了npm上,方便开发人员下载和应用。npm install 包名
node.js能做什么?
1,web服务器后台
2,命令行工具 npm hexo等命令
node.js运行环境安装:
👉进入官网下载
建议选择LTS(稳定版)
怎么算是安装成功了呢?
打开cmd, 输入node -v或者 node --version ,显示了版本号,就表示安装成功
记得去配置环境变量。这里不赘述啦。(我感觉只要涉及到后端的东西,都要配置变量。。)
前面说了,node可以让js代码脱离浏览器来运行了,那么,要怎么做呢? 来试一下吧~
打开编辑器,创建个js文件,如a.js (文件名不准用node.js)
var a = 'hello world !'
console.log(a)
在当前文件的目录下,右击空白处,选择opencmdhere,就可以打开控制台了。
输入命令 node a.js 回车
输出结果: hello world !
这样,就用node运行了js文件。不需要在浏览器中打开了。是不是变得更简单了呢?
HTTP
为了支持所有可能的 HTTP 应用程序,Node.js 的 HTTP API 都是非常底层的。 它仅进行流处理和消息解析。 它将消息解析为消息头和消息主体,但不会解析具体的消息头或消息主体。
怎么创建http
1,引入http模块 const http = require('http');
2,创建http服务 const server = http.createServer();
3,服务请求响应事件
①发送服务请求响应事件
server.on('request', (request, response) => console.log(‘收到客户端的请求了'));
这里的(request, response) 也可以简写为(req,res),他们分别是请求对象和响应对象
然后把下面的request和response分别换成req和res即可。 两个都是传参。
②写入响应内容response.write('响应内容'); 可以写多条
注意:响应内容是通过 用户打开链接http://localhost:3000/后 在网页显示的
server.on('request', (request, response) => {
response.write(‘收到客户端的请求了'));
response.write(‘hello node.js'));
});
③结束响应response.end() 告诉客户端,我的话说完了,你可以呈递给用户看了
server.on('request', (request, response) => {
response.write(‘收到客户端的请求了'));
response.write(‘hello node.js'));
response.end();
//平时res.write()基本不用,而是把响应的输出内容直接写进res.end()里面
});
4,服务连接端口 server.listen(3000, () => console.log('服务器启启动成功了, 可以通过localhost:3000/来访问'));
注意:这个服务器启动成功提示 是在命令行里面显示的 不是给用户看的
以上的request是请求的意思,可以写为req, response是响应的意思,可以写为res 。
现在创建的是简单的服务器,但是现在服务器能力还特别弱, 比如 server.on(‘request’, (request, response) => 这个响应事件中的request 是任何请求,也就说 用户在链接后面加上别的url内容,
服务器给的响应结果都是一样的,这就很糟糕了。 那么 在用户输入不同的url地址时 怎么给用户呈递不同的响应内容呢?
思考: 我希望 当用户发出不同的请求(url地址)时 服务器会给用户呈现出不同的响应内容 怎么做呢?
简单来说,就是根据用户输入不同的网址,会出现不同的页面
比如 :
用户的请求是 localhost:3000/index时 响应返回首页
用户的请求是 localhost:3000/login时 响应登陆
用户的请求是 localhost:3000/register时 响应注册
用户的请求是 localhost:3000/haha时 响应结果为 ‘哈哈哈’
根据不同的请求路径 发送给用户不同的响应结果:
1,获取请求路径
req.url 获取到的是端口号之后的那一部分路径
比如 http://localhost:3000/a , 这个网址的req.url 就是/a
所有的url都是以 / 开头的
2,判断路径 输出不同的处理响应结果
if (req.url == '/') { res.end('hello node')
} else if (req.url == '/index') { res.end('欢迎来到首页')
} else if(req.url == '/login'){ res.end('请登陆')
} else { res.end('你好呀 node')}
res.end()的响应内容只能是二进制数据或者字符串,不能是数字,对象,数组和布尔值。
现在说说node中的js,它包括ES和api
api又分为node自带封装的api, 别人写的文件, 自己写的文件
1,ECMAScript
没有BOM, DOM ,只有ES
2,核心模块
就算很多服务器级别的api,这些api绝大多数被封装到了一个有具体名字的
核心模块中了。比如 fs读取文件, http服务器等。
核心模块通过require引入。 例如 const http = require('http')
3,第三方模块
别人写的可以用来引入的js文件。
4,用户自定义模块
就是用户自己写的js文件
比如 用户写的b.js 文件。 内容是 console.log(‘我被a加载执行了’);
现在在a.js文件里引入用户自己的写的b.js文件
在a文件中引入b.js,并执行
require(’./b.js’); 也 是用require引入。
后缀名.js可以省略。平时写的时候都可以省略掉。
相对路径必须加 ./ 意思是当前目录
在node中,没有全局作用域,只有模块作用域。 意思是,在a.js中定义的变量,在b.js中访问不到。 在b.js中定义的变量,在a中访问不到。互不影响。
require有两个作用:
1,加载文件模块并执行里面的代码 比如 require(’./b.js’);
2,拿到被加载文件模块导出的接口对象exports
在每个文件模块中都提供了一个接口对象:exports
exports默认是一个空对象
如果想拿到被加载文件(b.js)中的数据,
需要把所有想让外部访问的成员都放到exports对象中。
举例:
a1.js中的代码:
let r = require('./b1');
console.log(r); // { f: '我被a1访问到了' }
如果想拿到b1文件中的f值。只需要提取就可以了。
console.log(r.f); // 我被a1访问到了
b1.js中的代码:
exports.f = ‘我被a1访问到了’;
这样就把f = '我被a1访问到了’放在对象中,被a1文件访问到了。
端口号
IP地址用来定位计算机
端口号用来定位具体的应用程序
举例 :http://localhost:3000/
localhost就是域名
localhost指向的是 127.0.0.1 这个本地ip地址
3000就是端口号
所有需要联网通信的软件 都必须具有端口号
端口号的范围在0~65536之间
在计算机中有一些默认的端口号,最好不要去使用
例如http服务的端口号80
开发过程中常用的3000,5000端口。也没为啥,常用罢了。
可以同时开启多个服务,但是一定要确保不同的服务占用的是不同的端口号
响应内容类型 content-type
res.setHeader('Content-Type', 'text/plain; charset=utf-8')
表示响应内容是纯文本模式
res.setHeader('Content-Type', 'text/html; charset=utf-8')
表示响应的内容是html模式,浏览器解析时 会把标签去掉 显示成HTML文档
除了Content-Type 可以用来指定编码, 还可以在HTML页面中通过meta元数据来声明当前文本的编码格式。浏览器也会识别它。
举例:
const http = require('http');
const server = http.createServer();
server.on('request', (req, res) => {
// res.end('hello node我来了');
res.setHeader('Content-Type', 'text/html; charset=utf-8');
res.end('<p>hello node我来了<a href="">点我</a></p>');
});
server.listen(3000, () => console.log('Server is running...'));
在http内访问文件
1,先引入fs读取文件模块
2,然后fs.readFile(‘被访问的文件’, 回调函数)
文件可以是图片,HTML文档,css样式,js文件等等。
每种文件对应格式是不一样的,
点击查看各种文件格式
比如
HTML文件的格式,就是text/html
jpg的对应格式是 image/jpeg ,但是图片就不需要在后面写charset编码了。
举例:
const http = require('http')
const fs = require('fs')
const server = http.createServer()
server.on('request', (req, res) => {
// 一个请求对应一个响应,如果一个请求的过程中,已经结束响应了,则不能重复发送响应。没有请求 就没有响应
let url = req.url
fs.readFile('./html01.html', (err, data) => {
if (err) {
res.setHeader('Content-Type', 'text/plain; charset=utf-8')
res.end('文件读取失败!')
return //结束执行
}
res.end(data)
console.log(data.toString())
})
})
server.listen(5000, () => console.log('Server is running...'))
小知识点:js代码分号的问题
有三种情况记得在符号前加分号
1,以小括号( 开头的
2,以中括号 [ 开头的
3, 以 模板字符 反引号`开头的
其他情况下, 都可以不加分号
\
模块系统
什么是模块化?
-有文件作用域
-有通信规则
加载 require
require的作用:
-执行被加载模块中的代码
-得到被加载模块中的接口对象exports ,require(‘文件路径’)得到的就是exports对象了。
require的加载机制:
-不会重复加载 举例 main.js a.js b.js 优先从缓存加载,提升加载效率
-判断模块标识 即require(‘模块标识’)
如果标识是路径形式的 如 / (根目录) ./当前目录(不可省略) …/ (上级目录),这个模块就是自定义模块。例如 require(‘./a.js’) 。
如果不是路径形式的,例如 require(‘fs’), 这个模块就是核心模块。核心模块本质上也是文件。
-导出 exports
第三方模块: 所有第三方模块 都要通过npm进行下载 使用的时候就可以通过require(‘包名’)来使用
第三方的包和核心模块的包绝对是不会出现一样的名字。 比如核心模块里有fs, 那么第三方模块里就不会有一个叫fs 的包名。
模块查找规则
情形一:当模块有路径没后缀时:
如 require('./find')
情形二:当模块没路径没后缀时:
如require('find')
-导出多个成员(整个exports对象)
exports.a = 123
exports.b = 'hello'
exports.c = () => console.log('ccc')
exports.d ={ foo: 'bar'}
-导出单个成员(拿到别的文件的单个函数或者字符串)
module.exports = 'hello'
得到的就是hello字符串
exports和module.exports的关系:
结论:
exports是module.exports的一个引用,两者是等价的。
console.log(exports === module.exports) //true
exports.foo = ‘bar’ 等价于 module.exports.foo = ‘bar’
原理:
在Node中,每个模块内部都有自己的一个module对象
在module对象中,有一个叫exports的成员,也是一个对象
也就是说 如果你需要对外导出成员,只需要把导出的成员挂在到module.exports中 比如 module.exports.foo = 'bar' 导出成员foo
let module = {
exports: {
foo: 'var
}
然后程序中还有一句隐形代码 let exports = module.exports
如果两者中任意一个重新赋值,都会断开两者的引用关系
比如:
exports.a = 'bar'
module.exports.a = 123
//在这里 给exports进行赋值:
exports = {
a: 'hah',
b: 0
}
exports.a = '会不会改变呢'
exports.b = 1
module.exports.b = 2
const foo = require('./exports和module.exports')
console.log(foo) // 输出结果是 { a: 123, b: 2 }
我们发现,exports和module.exports开始的时候,指向的是同一个空间内的值。 给expors赋值了a和b后, 最后输出结果都和exports无关了。 因为赋值之后,exports的地址被改变了,两者之间的引用就断开了。exports的地址(也就是指针指向)已经指向了一个新的空间,不管exports的值怎么改变,都不会对输出结果产生影响。 程序最终输出的是module.exports 的值, 和exports无关。
如果想让exports重新影响输出结果,就需要重新建立引用关系 exports = module.exports ,让exports的指针再指向和module.exports同一个空间。 建立关系后,输出结果为 { a: ‘会不会改变呢’, b: 2 }
实际开发中,如果实在分不清楚的话,可以只用module.exports去导出。因为最终输出的值都是module.exports
模块包含知识:
1,ECMAScript
2,核心模块
node内部封装的api,比如
-操作文件的fs
-http服务的http
-url路径操作模块
-path路径处理模块
-os操作系统信息
3,第三方模块
4,自定义模块
-npm
node package manager : node包管理器 , 用来下载第三方的包的
-package.json
每个包的根目录下都要有一个package.json,相当于产品说明书
这个文件可以通过npm init 初始化出来
执行 npm install 包名 的时候,建议在包名前都加上--save, 可以下下载包名时 保存文件依赖项信息。
如果node_modules被删除了,也不用担心, 在命令行输入 npm install 会把所有的依赖项重新下载回来
–npm命令行工具
只要安装了node 就已经自动安装了 npm
npm也有版本这个概念 在命令行中输入 npm --version或者 npm -v 可以查看当前使用的版本号
可以在命令行中输入 npm install --global npm 对npm版本进行升级
–npm常用命令
-npm init -y 快速生成package.json文件的
-npm install 包名 :只下载这个包, 不保存依赖项
-npm install --save 包名 : 下载这个包 并保存依赖项(package.json文件中的dependencies选项)
也可以用npm i -S 包名 这种简写形式
-npm uninstall 包名 :只删除这个包。 简写形式 npm un 包名
-npm uninstall 包名 --save :删除这个包 并删除这个包的依赖项
-npm 命令 --help :查看指定命令的使用帮助
–解决npm下载慢的问题
因为npm存储包的服务器在国外,下载速度会很慢,所以需要解决这个问题。
npm.taobao.org/ 淘宝的开发团队把npm在国内做了一个备份。
方法一: 安装cnpm 并使用淘宝服务器来下载, 以后要把npm换成cnpm
安装淘宝的cnpm: 输入命令行 npm install --global cnpm 安装全局的cnpm
接下来,下载包的时候 用cnpm install 包名 就可以下载了
方法二(推荐) :不想安装cnpm,又想使用淘宝服务器来下载,不想改变npm命令
在命令行输入 npm config set registry https://registry.npm.taobao.org
命令行输入 npm config list 就可以在配置信息里看到registry了
然后下载的时候 就用npm install 包名 --save 就可以了。 会默认使用淘宝服务器来下载
方法三: 用nrm
1, 使用npm install nrm -g 下载nrm
2,用nrm下载的时候 命令行输入 nrm use 包名 即可
-模板引擎 art-template(后面还有更好用的方法,所以这里对模板引擎可以了解一下)
介绍
参考文档
文档中有详细说明,这里不赘述了~
这里有个案例,可以了解一下相关用法:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>art-template在网页中的用法 带遍历</title>
</head>
<body>
<!-- 1,先引用template-web.js -->
<script src="../node_modules/art-template/lib/template-web.js"></script>
<!-- 2,创建在网页中输入的位置
如果不创建 那就用console.log在console里面打印 -->
<div id="here"></div>
<!-- 3,创建模板 浏览器版本无法加载外部文件,需要给模板创建一个id-->
<script type="text/template" id="tpl">
大家好,我叫: {{ name }}
我今年 {{ age }} 岁了
我来自 {{ province }}
我喜欢: {{ each hobbies }} {{ $value }} {{ /each }}
<!-- each遍历 -->
</script>
<!-- 4,根据模板名来渲染模板 template把对象内的name age等 属性渲染到id为tpl模板里, 渲染后的结果用content来接收-->
<script>
let content = template('tpl', {
name: '迪丽热巴',
age: 18,
province: '北京',
hobbies: [
'唱歌',
'演电影',
'睡觉',
'打豆豆'
]
})
//console里面输出
//console.log(content)
// 大家好,我叫: 迪丽热巴
// 我今年 18 岁了
// 我来自 北京
// 我喜欢: 唱歌 演电影 睡觉 打豆豆
// 5,在网页中输出 网页不接受文件系统 所以要通过innerHTML把内容接收到页面上
let here = document.querySelector('#here')
//把呈现的内容 传递到div中
here.innerHTML = content
// 大家好,我叫: 迪丽热巴 我今年 18 岁了 我来自 北京 我喜欢: 唱歌 演电影 睡觉 打豆豆
</script>
</body>
</html>
art-template的API:
1, template(filename, content)
2, .compile(source, options)
3, .render(source, data, options)
\
-Express 第三方开发框架 基于原生node 高度封装了 http模块
原生的http在某些方面表现不足以应对我们的开发需求,所以我们就需要使用框架来提升我们的开发效率。
框架的目的就是提高效率,让我们的代码高度统一。
在Node中,有很多web开发框架,这里先学习express。
express是专门为node.js开发的一款快速、开放的、轻量级的框架。
下载:
第一步: win + R ,输入cmd,打开控制台
第二步: 输入 npm install -g express-generator
第三步: 输入 npm install -g express
第四步: 输入 express --version ,回车,如果出现了 Express 的版本号,说明 Express 安装成功。
使用: 先引入express包。 const express = require('express')
举例:
const express = require('express')
let app = express()
app.get('/', (req, res) => {
res.send('想看点什么内容呢?')
})
app.get('/index', (req, res) => {
res.send('<a href="">欢迎来到首页!</a>')
console.log(req.url)
})
app.get('/login', (req, res) => {
res.send('请登陆')
})
app.listen(3000, () => console.log('app is running'))
-这里需要响应几次,就把app.get复制几份就可以了。
-res.send()也不用担心Content-Type的问题。 因为在express里,已经给自动处理了。
那么怎么公开指定目录,分享静态资源呢,比如想访问public文件夹里的main.js,需要怎么做呢
静态资源就是css, js , img等。
app.use('/public/', express.static('./pubic/') )即可。
举例: 读取public文件夹里的 sta.js文件 注意这里的路径不能有中文
const express = require('express')
const app = express()
app.use('/public/', express.static('./public/'))
app.listen(3000, () => console.log('app is running...'))
//打开网页连接 http://localhost:3000/public/sta.js 即可读取到js文件
-nodemon
nodemon是一个基于Node.js开发的第三方命令行工具,辅助项目开发。
在Node.js中,每次修改文件都要在命令行工具中重新执行该文件,非常繁琐。 所以,nodemon就是用来解决这个问题的。
使用步骤:
-输入命令 npm install nodemon -g 下载
-在命令行工具中使用modemon命令替代node命令来执行文件。
只要是nodemon执行的文件,它会自动监视文件,如果被执行的文件有变动,它会自动重启服务器。
-在express中配置使用art-template模板引擎
👉官方文档
安装:
npm install --save art-template
npm install --save express-art-template
配置:
配置使用art-template模板引擎
.enigne的第一个参数art表示模板文件的格式 意思是当渲染以.art结尾的文件时,使用art-template模板引擎
如果把这里的art参数换成html,就表示以.html结尾的文件时,使用模板引擎渲染
express-art-template是专门用来在express中把art-template整合到express中
express-art-template依赖了art-template
app.engine('art', require('express-art-template'));
express 为response响应对象提供了一个方法:render
render方法默认是不可以使用的,但是如果配置了模板引擎,它就可以使用了
res.render(‘html模板名’, {模板数据})
第一个参数不能写路径,默认会去项目中的views目录查找模板文件
也就是说express有一个约定:开发人员把所有的视图文件都放到views文件夹中
使用:
举例
app.get('/', (req, res) => res.render('title.html', {
title: '迪丽热巴'
}) )
//render默认会去项目中的views文件夹里面找title.html文件
//views是约定的视频文件存储目录, 固定用法。不要去修改。
-基本路由
路由就是请求什么,响应什么。
请求方法分为get 和 post 。
-get:
app.get('/', (req, res) => res.send('hello express'))
-post:
app.post('/', (req, res) => res.send('hello express'))
-在express中获取表单get的请求参数
express内置了一个api,可以直接通过req.query来获取
-在express中获取表单post的请求参数
在express中没有内置获取表单POST请求体的api, 这里需要我们使用一个第三方的包body-parser
-安装
npm install body-parser --save
-配置
先引入 const bodyParser = require('body-parser')
再配置
//配置body-parser中间件 专门用来解析表单post请求体
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
//只要加入这个配置,则在req请求对象上会多出来一个属性: body
//也就是说 你就可以直接通过req.body来获取表单POST请求体数据了
-Mongodb 数据库
为什么使用数据库?
- 动态网站中的数据都是存储在数据库中的
- 数据库可以用来持久存储客户端通过表单收集的用户信息
- 数据库软件本身可以对数据进行高效的管理
什么是数据库?
数据库即存储数据的仓库,可以将数据进行有序的分门别类地存储。它是独立于语言之外的软件,可以通过API去操作它。
点击👉MongoDB下载与安装
(下载过程中,可能会遇到不少雷区,建议百度解决,我自己也是搞了一个多小时才弄好)
连接本机的mongodb服务 : 命令行里输入 mongo
退出连接 : CTRL + c 或者关闭控制台
-基本命令
-show dbs 查看显示所有数据库
-db 查看当前操作的数据库
-use 数据库名称 切换到指定的数据(如果没有会新建)
-在Node中如何操作mongodb
-使用官方的mongodb包来操作
-使用mongoose来操作mongodb数据库
例如使用mongoose提供的connect方法即可连接数据库。
mongoose.connect('mongodb://localhost/库名')
.then(() => console.log('数据库连接成功')
.catch(err => console.log('数据库连接失败', err))
-安装 npm install mongoose
MongoDB数据库的基本概念
-可以有多个数据库
-一个数据库中可以有多个集合(表)
-一个集合中可以有多个文档(表记录)
-文档结构很灵活,没有任何限制,还可以为空
{
qq:{
user: [
{name: 'zhangsan', age: 15},
{name: 'lisi', age: 16},
{name: 'wangwu', age: 17},
...
],
products: [
{ }...
]
},
taobao: {
user: [
{...},
{...}
],
produ: [...]
}
}
{ }里面的qq和taobao都分别是一个数据库, 数据库里面的user数据就是一个集合,
user里面的{…}就是一个文档。
应用步骤:
//1,引入mongoose包
const mongoose = require('mongoose')
//2,调用Schema集合方法
const Schema = mongoose.Schema
//3,连接数据库
//指定连接的数据库不需要存在,当你插入第一条数据之后,这个被连接的数据库就会自动创建出来
mongoose.connect('mongodb://localhost/itcast')
//4,设计文档结构(表结构)
//字段名称就是表结构中的属性名称
//约束的目的是为了保证数据的完整性,不要有脏数据
var userSchema = new Schema({
username: {
type: String,
required: true //这个必须有
},
password: {
type: String,
required: true
},
email: {
type: String
}
})
//5,发布文档模型
//model()中的第一个字符串User会变为users集合名称
//第二个参数 是只应用哪个结构 这礼是应用userSchema结构
const User = mongoose.model('User', userSchema)
//6,创建集合实例
const user = new User({
username: 'admin',
password: '123456',
email: 'admin@admin.com'
})
//7,将数据保存到数据库中
user.save((err, ret) => {
if (err) {
console.log('save faile..')
} else {
console.log('save success...')
console.log(ret)
}
})
//8,用管理员模式打开cmd, 连接数据库 net start mongoDB 不要关掉
//9, 另开启一个cmd, node 运行该js文件
MongoDB的增删改查操作
上述应用举例中 6,创建集合实例的
第二种方法:
User.create(
{
username: 'admin',
password: '123456',
email: 'admin@admin.com'
}
)
注意:和数据库相关的操作都是异步操作。
查:
//查询所有文档
User.find()
.then(result => console.log(result))
//根据条件查找文档
User.findOne({username: 'admin'})
.then(result => console.log(result))
//匹配大于 小于
User.find({age: {$gt:20, $lt:50} })
.then(result => console.log(result))
//匹配包含
User.find({hobbies: {$in: ['睡觉']} })
.then(result => console.log(result))
//所有爱好是睡觉的文档都会被查询输出
//选择要查询的字段
User.find()
.select('name email')
.then(result => console.log(result))
如果查找条件为空,默认查找当前集合的第一个文档: 返回的是一个对象,不是数组了。
如果查找条件不为空,就返回适配查找条件的第一个文档对象。
注意:如果查询的字段里不想包含id ,那就在_id前面加个-
比如:User.find().select('name email -_id').then(result => console.log(result))
//将数据按照年龄进行排序
User.find()
.sort('age')
.then(result => console.log(result))
//注意这个排序默认是升序的,也就是从小到大排序
//skip 跳过多少条数据 limit 限制查询的数量
User.find()
.skip(2)
.limit(2)
.then(result => console.log(result))
删:
//删除单个文档
User.findOneAndDelete({})
.then(result => console.log(result))
//删除多个
User.deleteMany({})
.then(result => console.log(result))
//删除多个的时候,如果删除条件为空,就默认删除所有文档。
//返回值是一个对象,对象有两个值,
//一个值是删除文档的数量,一个值是显示删除成功与否
改:
//改单个
User.updateOne({查询条件}, {要修改的值})
.then(result => console.log(result))
//改多个
User.updateMany({查询条件}, {要修改的值})
.then(result => console.log(result))
mongoose验证:
在创建集合规则时,可以设置当前字段的验证规则,验证失败则输入插入失败。
- require: true 必传字段
- minlength: 3 字符串最小长度为3
- maxlength: 20 字符串最大长度为20
- min: 2 输入数值最小为2
- max: 10 输入数值最大为10
- enum: [‘html’, ‘css’, ‘javascript’, ‘node.js’]
- trim: true 去除字符串两边的空格
- validate: 自定义验证器
- default: 默认值
应用举例:
const postSchema = new mongoose.Schema({
title: {
type: String,
//必选字段
require: [true, '请输入文章标题'],
//字符串最小长度
minlength: [2, '文章长度不能小于2'],
//字符串最大长度
maxlength: [5, '文章长度最大不能超过5'],
//去除字符串两边的空格
trim: true
},
age: {
type: Number,
min: 18,
max: 100
}
})
const Post = mongoose.model('Post', postSchema)
Post.create({title: 'aa', age: 60})
.then(result => console.log(result))
集合关联:
通常 不同集合的数据之间是有关系的,例如文章信息和用户信息存储在不同集合中,但文章都是某个用户发表的,要查询文章的所有信息 包括发表用户,就需要用到集合关联。
实用举例:
//用户集合
const User = mongoose.model('User', new mongoose.Schema({ name: {type: String}}))
//文章集合
const Post = mongoose.model('Post', new mongoose.Schema({
title: { type: String }
//使用ID将文章和作者集合进行关联
author: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'}
}))
//联系查询
Post.find()
.populate('author')
.then((err, result) => console.log(result))
其他相关资料: