Node基础知识整理

168 阅读15分钟

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官方文档 👉点击查看

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网站

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模块

Express官方文档 点击查看👇

​ 原生的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下载与安装
(下载过程中,可能会遇到不少雷区,建议百度解决,我自己也是搞了一个多小时才弄好)

​ 连接本机的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))

其他相关资料:

👉gulp快速入门
👉Bootstrap英文官网
👉Bootstrap中文官网
👉ES6知识回顾