注:该笔记来自于视频Node.JS-黑马程序员
概述
express是高度封装了http的第三方框架。
express官网:http://expressjs.com/
只需要像安装其他包那样,直接执行npm install express --save
命令安装后就可以使用了。
Hello World
Hello World
第一次使用:
// 第一步,引入express
var express=require("express");
// 第二步,创建服务器应用程序,即原来的http.createServer()
var app=express();
// 当服务器收到get请求 / 的时候,执行回调函数
app.get('/',function (request, response) {
response.send("hello express!");// 发送数据到客户端,但原来的write、end方法都可以使用,但推荐使用send方法。
});
app.get('/hello',function (request, response) {
response.send("你好,Express!");
});
// 监听端口,相当于原来的server.listen()
app.listen(8888,function () {
console.log("app is running at port 8888.");
});
公开静态资源
如果要公开静态目录中的资源,可以设置这样的代码:
// 公开指定目录,该目录下存放的是静态资源如图片、css、js等
// 其中'/public/'表示可以通过/public/xx的方式访问'./public/'目录下的静态资源文件xx
app.use('/public/',express.static('./public/'));
就可以通过http://localhost:8888/public/star.jpg访问public目录下的star.jpg文件了。
操作路径问题
关于文件操作路径和模块操作路径的问题:
/**
* 如果这里不添加".",则也是从磁盘根目录开始
* 所以模块加载的路径中的相对路径不能省略"./"
*/
var foo = require('/data/foo.js');
var foo = require("./data/foo.js")
/**
* 在文件操作的相对路径中
* ./data/a.txt是相对于当前目录
* data/a.txt是相对于当前目录
* /data/a.txt表示绝对路径,是当前文件模块所处磁盘根目录
* C:/Users/data/a.txt表示绝对路径
*/
fs.readFile('./data/a.txt', function (err, data) {
});
nodemon
修改完代码后自动重启,即热部署。安装这个插件后,就可以不用每次修改代码后都重启程序,可以节约时间。
使用第三方命令行工具:nodemon
来解决修改代码后重启服务器问题。
安装:npm install nodemon --global
安装完成后,使用nodemon 启动文件名
来启动服务,会监视文件的变化,当文件发生变化时,自动重启服务器。
node app.js // 例如原来启动app.js
nodemon app.js // 安装nodemon后启动app.js
使用nodemon --version
来验证是否安装成功。
基本使用
GET请求和POST请求
express获取GET请求和POST请求分别通过如下两个方法,并在对应的回调函数中进行请求的处理和响应:
-
app.get(path, callback);
:处理GET请求。 -
app.post(path, callback);
:处理POST请求。
注意:
-
app
指的是通过express()
创建的服务器应用程序对象。 -
path
是请求路由。 -
callback
是一个回调函数,有两个参数request
和response
,分别是http的请求对象和响应对象,既可以调用http上的方法,也可以调用express提供的方法。
// 当服务器收到get请求 / 的时候,执行回调函数
app.get('/', function (request, response) {
response.send("hello express!");
});
app.get('/hello', function (request, response) {
response.send("你好,Express!");
});
// 当服务器收到post请求/submit的时候,执行对应的回调函数
app.post('/submit', function (request, response) {
response.send("这是一个POST请求");
});
开放静态资源
静态资源就是一些html、css、js以及图片等文件。在http和express中是无法直接通过路径进行访问的,需要配置进行开放。有如下三种方式:
// 公开指定目录,该目录下存放的是静态资源如图片、css、js等
// 其中'/public/'表示可以通过/public/xxx的方式访问'./public/'目录下的静态资源文件xxx
// 例如:http://localhost:8888/public/star.jpg
app.use('/public/', express.static('./public/'));
// 其中'/abc/d/'表示可以通过'/abc/d/xxx'的方式访问'./public/'目录下的静态资源文件xxx
// 例如:http://localhost:8888/abc/d/star.jpg
app.use('/abc/d/', express.static('./public/'));
// 当省略第一个参数的时候,则可以通过省略'/public'的方式来访问,这种方式的好处是可以省略'/public/'
// 例如:http://localhost:8888/star.jpg
app.use(express.static('./public/'));
在express中使用模板引擎art-template
参考官方文档:https://aui.github.io/art-template/
- 第一步,安装
在项目的根目录下执行npm安装命令:
npm install art-template --save
npm install express-art-template --save
- 第二步,配置。
在导入了express模块的所在js文件中配置express-art-tempalte:
// 第一步,引入express
// var express = require("express");
// 第二步,创建服务器应用程序,即原来的http.createServer()
// var app = express();
// 配置express-art-template,前面的四行代码是为了让你知道在哪配置express-art-template
// 配置express-art-template模板引擎
// 第一个参数表示当以.html结尾的文件的时候,使用art-template模板引擎
// express-art-template是专门用来在express中把art-template整合到express中的
// 虽然外面不需要引入art-template,但也必须安装,因为express-art-template依赖了art-template
app.engine('html', require('express-art-template'));
- 第三步,使用
还是通过response.render(path, object);
来使用art-template模板引擎,其中path
参数直接写文件名即可,它会自动去views文件夹下找对应的文件,所以通常我们会自己创建views文件夹作为存放html视图文件的目录;object
是一个对象,表示要传入到对应模板文件中的数据对象。代码示例如下:
app.get('/hello', function (request, response) {
// express默认会去项目中的views目录中找hello.html文件
// express为Response响应对象提供了一个render()方法
// 该方法默认是不可以使用的,但如果配置了模板引擎就可以使用了
// 第一个参数不能写路径,写文件名即可,因为默认会去views目录中查找模板文件
// 也就是说express默认约定开发人员把所有的视图文件都放到views目录中
response.render('hello.html', {
title: 'Hello World'
});
});
- 第四步,扩展
如果希望默认的views
视图渲染存储目录,则可以通过如下方式进行修改:
// 注意,第一个参数views一定不能写错
app.set('views', 目录路径);
重定向
express的response.redirect('/')
也可以实现重定向。
app.get('/send', function (request, response) {
// 以前重定向的方法
response.statusCode = 302;
response.setHeader('Location', "/");
// 使用express后的重定向方法
response.redirect('/');
});
在Express中获取表单GET请求参数
express内置了一个API,可以直接通过request.query
来获取请求参数,是一个对象。
app.get('/hello', function (request, response) {
// http://localhost:8888/hello?name=zhangsan&age=12&sex=m
console.log(request.query);// { name: 'zhangsan', age: '12', sex: 'm' }
console.log(request.query.name);// zhangsan
console.log(request.query.age);// 12
console.log(request.query.sex);// m
});
在Express中获取表单POST请求参数
在express中没有内置获取表单POST请求体的API,所以需要使用一个第三方包:body-parser
。
- 第一步,安装
body-parser
npm install body-parser --save
- 第二步,配置
在引入了express模块中的js文件引入body-parser
并进行配置:
// 第一步,引入express
// var express = require("express");
// 引入body-parser
var bodyParser = require('body-parser');
// 第二步,创建服务器应用程序,即原来的http.createServer()
// var app = express();
// 配置body-parser
// 只需要加入这个配置,则会在请求对象request上多出来一个body属性
// 就可以直接通过request.body来获取表单POST请求体数据
// parse application/x-www-form-urlencoded
// 被注释掉的express导入代码是为了让你关注body-parser的导入和配置
app.use(bodyParser.urlencoded({extended: false}));
// parse application/json
app.use(bodyParser.json());
- 第三步,使用
请求对象request会多一个body
属性,就是POST表单提交的数据。
// 当服务器收到post请求/submit的时候,执行对应的回调函数
app.post('/submit', function (request, response) {
// http://localhost:8888/submit
console.log(request.body);// [Object: null prototype] { username: 'zhangsan', password: '123456' }
console.log(request.body.username);// zhangsan
console.log(request.body.password);// 123456
response.send(request.body);// {"username":"zhangsan","password":"123456"}
});
处理404
在路由的最后(即post和get最后)添加如下代码:
// 如果要定制404,需要通过中间件来配置,只需要在路由之后添加如下代码
app.use(function (request, response) {
// 所有未处理的请求路径都会跑到这里来
// 处理404的逻辑
});
中间件
参考文档:http://expressjs.com/en/guide/using-middleware.html
概念
Express的中间件就是一个请求处理方法,把用户从请求到响应的整个过程分发到多个中间件去处理,提供代码的复用性。
其实Express的中间件非常类似于Servlet的过滤器和SpringMVC的拦截器。
中间件通过app.use()
方法进行设置。
中间件分类
应用程序级别的中间件
匹配所有的请求路径,不关心任何请求路径和请求方法(GET和POST)的中间件。格式如下:
// app是express实例
app.use(function(request,response,next){
// 对request和response的处理
next();
}
例如:
app.use(function (request, resonse, next) {
// request:请求对象
// response:响应对象
// next:是一个函数,表示通过该中间件。当一个请求进入中间件后,如果需要请求另外一个方法则需要使用next()方法。next是一个方法,用来调用下一个中间件。注意:next()方法调用下一个方法的时候,也会匹配请求路径和方法(而不是调用紧挨着的哪一个)
console.log(request.url);
next();// 表示继续下一个中间件
});
而还有一种关心请求路径和请求方法的中间件,格式如下:
app.use(路径, function(request, response, next){
// 对request和response的处理
next();
});
例如:
app.use('/hello', function (request, response, next) {
// 只有'/hello'路径的请求才会进入该中间件
console.log(request.url);
next();
});
路由级别的中间件
严格匹配请求路径和请求方法的中间件。
get:
app.get('/',function(req,res){
res.send('get');
});
post:
app.post('/a',function(req,res){
res.send('post');
});
put:
app.put('/user',function(req,res){
res.send('put');
});
delete:
app.delete('/delete',function(req,res){
res.send('delete');
});
错误处理中间件
app.use(function(err,req,res,next){
console.error(err,stack);
res.status(500).send('Something broke');
});
配置使用404中间件:这个顺序必须放到最后一个中间件,即最后一个use也该放到get、post后面
app.use(function(req,res){
res.render('404.html');
});
配置全局错误处理中间件:
app.get('/a', function(req, res, next) {
fs.readFile('.a/bc', funtion() {
if (err) {
// 当调用next()传参后,则直接进入到全局错误处理中间件方法中
// 当发生全局错误的时候,我们可以调用next传递错误对象
// 然后被全局错误处理中间件匹配到并进行处理
next(err);
}
})
});
//全局错误处理中间件
app.use(function(err,req,res,next){
res.status(500).json({
err_code:500,
message:err.message
});
});
内置中间件
express提供一个内置中间件,可以用来开放静态资源。如:
app.use(express.static('public'))
具体请参考文档:express.static()
第三方中间件
我们使用过一些第三方中间件,如body-parse
处理POST请求体、如session
处理session信息保存。
- body-parser
- compression
- cookie-parser
- mogran
- response-time
- server-static
- session
参考文档:http://expressjs.com/en/resources/middleware.html
Express的CRUD
准备工作
按照下图创建文件夹和文件:
- node_modules:安装包的时候会自动创建,管理着第三方包。
- public:存放项目需要用到的一些公共资源,如css、js、图片等。
- views:该文件夹存放着html视图文件。
- app.js:项目的启动程序文件。
- db.json:由于没有使用数据库,所以将数据持久化存储到本地文件中,以json格式存储。
- package.json:包说明文件,在使用
npm init
命令时自动创建。 - package-lock.json:包版本锁定文件,也是在安装包时自动创建的。
- README.md:项目说明文件,自己写一些说明给该项目。
- router.js:处理路由的文件。
- student.js:数据增删改查操作,只是是将数据存储到db.json文件中。
安装包:在该项目下打开命令行窗口执行如下命令安装需要的包。
npm install --save express
npm install --save body-parser
npm install --save art-template
npm install --save express-art-template
初步创建app.js文件,让程序基本运行起来。
// 导入express模块
var express = require('express');
// 创建服务器
var app = express();
// 处理请求
app.get('/', function (request, response) {
response.send('hello world.');
});
// 监听端口
app.listen(8989, function () {
console.log('服务运行中,可通过 http://127.0.0.1:8989/ 访问...');
});
路由设计如下:
路由设计
请求方法 | 请求路径 | get参数 | post参数 | 备注 |
---|---|---|---|---|
GET | /students | 渲染学生列表 | ||
GET | /students/newPage | 学生新增页面 | ||
POST | /students/new | name、sex、age | 新增学生 | |
GET | /students/editPage | 学生编辑页面 | ||
POST | /students/edit | id | 编辑学生 | |
GET | /students/delete | id | 删除学生 |
创建路由文件router.js
将所有的请求路由写在router.js文件中:
// 渲染学生列表页面
app.get('/students', function (request, response) {
});
// 渲染学生新增页面
app.get('/students/newPage', function (request, response) {
});
// 新增学生
app.get('/students/new', function (request, response) {
});
// 渲染学生编辑页面
app.get('/students/editPage', function (request, response) {
});
// 编辑学生
app.get('/students/edit', function (request, response) {
});
// 删除学生
app.get('/students/delete', function (request, response) {
});
上面代码的app应该来自app.js中的app对象,那么如何将app.js与router.js文件关联起来呢?
第一种方式:不推荐。
第二种方式:使用express提供的路由挂载方式。
所以此时app.js文件内容如下:
// 导入express模块
var express = require('express');
// 导入路由router.js
var router = require('./router');
// 创建服务器
var app = express();
// 把路由容器挂载到app服务中
app.use(router);
// 监听端口
app.listen(8989, function () {
console.log('服务运行中,可通过 http://127.0.0.1:8989/ 访问...');
});
// 将app对象暴露出去
module.exports = app;
router.js
// 0.Express提供了一种更好的方式,专门用来包装路由
var express = require('express');
// 1.创建一个路由容器
var router = express.Router();
// 2.router.get()或router.post()就是将路由都挂载到router路由容器中
// 渲染学生列表页面
router.get('/students', function (request, response) {
});
// 渲染学生新增页面
router.get('/students/newPage', function (request, response) {
});
// 新增学生
router.post('/students/new', function (request, response) {
});
// 渲染学生编辑页面
router.get('/students/editPage', function (request, response) {
});
// 编辑学生
router.post('/students/edit', function (request, response) {
});
// 删除学生
router.get('/students/delete', function (request, response) {
});
// 3.把router暴露出去
module.exports = router;
所以最后配置好的app.js
文件内容如下:
// 导入express模块
var express = require('express');
// 导入路由router.js
var router = require('./router');
// 引入body-parser
var bodyParser = require('body-parser');
// 创建服务器
var app = express();
// 配置body-parser
app.use(bodyParser.urlencoded({extended: false}));
// 配置express-art-template模板引擎
app.engine('html', require('express-art-template'));
// 公开指定目录,该目录下存放的是静态资源如图片、css、js等
app.use('/public/', express.static('./public/'));
// 把路由容器挂载到app服务中
app.use(router);
// 监听端口
app.listen(8989, function () {
console.log('服务运行中,可通过 http://127.0.0.1:8989/ 访问...');
});
// 将app对象暴露出去
module.exports = app;
视图文件
students.html
:学生列表页。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>学生列表页</title>
</head>
<body>
<a href="/students/newPage">添加学生</a>
<table border="1" cellspacing="0">
<tr>
<th>ID</th>
<th>姓名</th>
<th>性别</th>
<th>年龄</th>
</tr>
{{ each students }}
<tr>
<td>{{$value.id}}</td>
<td>{{$value.name}}</td>
<td>{{$value.sex}}</td>
<td>{{$value.age}}</td>
<td>
<a href="/students/delete?id={{ $value.id }}">删除</a>
<span> | </span>
<a href="/students/editPage?id={{ $value.id }}">编辑</a>
</td>
</tr>
{{ /each }}
</table>
</body>
</html>
add-student.html
:添加学生页面。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>添加学生</title>
</head>
<body>
<form action="/students/new" method="post">
姓名:<input type="text" name="name" placeholder="请输入学生姓名..."><br/>
性别:<input type="radio" name="sex" value="男"/>男<input type="radio" name="sex" value="女"/>女<br/>
年龄:<input type="number" name="age" placeholder="请输入学生年龄..."/><br/>
<input type="submit" value="添加学生"/>
</form>
</body>
</html>
edit-student.html
:编辑学生页面。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>编辑学生</title>
</head>
<body>
<form action="/students/edit" method="post">
<input type="text" name="id" value="{{ student.id }}" hidden="hidden">
姓名:<input type="text" name="name" placeholder="请输入学生姓名..." value="{{ student.name }}"><br/>
性别:
{{ if student.sex===1}}
<input type="radio" name="sex" value="男" checked="checked"/>男
<input type="radio" name="sex" value="女"/>女
{{ else if student.sex===0}}
<input type="radio" name="sex" value="男"/>男
<input type="radio" name="sex" value="女" checked="checked"/>女
{{ /if }}
<br/>
年龄:<input type="number" name="age" placeholder="请输入学生年龄..." value="{{ student.age }}"/><br/>
<input type="submit" value="修改"/>
</form>
</body>
</html>
CRUD
- 查询学生
在student.js
文件中添加操作从db.json
文件中查询数据的函数:
var fs = require('fs');
var dbPath = './db.json';
/**
* 发现所有学生
* @param callback 回调函数,有两个参数:err表示错误对象;data表示学生列表对象
*/
module.exports.findAll = function (callback) {
fs.readFile(dbPath, function (err, data) {
if (!err) {
callback(null, JSON.parse(data.toString()).students)
}
return callback(err);
});
};
/**
* 根据学生id来发现学生
* @param id 学生id
* @param callback 回调函数
*/
module.exports.findById = function (id, callback) {
fs.readFile(dbPath, function (err, data) {
if (err) {
return callback(err);
}
// 获取学生列表
var students = JSON.parse(data.toString()).students;
// 获取数组中指定id的学生
var student = students.find(function (item) {
return parseInt(item.id) === parseInt(id);// 注意"==="比较必须类型和值都相等
});
// 传递给回调函数
callback(null, student);
});
};
在router.js
路由文件中处理查询请求/students
,代码如下:
var Student = require('./student');
// 渲染学生列表页面
router.get('/students', function (request, response) {
Student.findAll(function (err, data) {
if (err) {
response.status(500).send('Server Error.')
} else {
response.render('students.html', {
students: data
});
}
});
});
效果如下:
- 添加学生
在student.js
文件中添加函数来对新增数据操作的处理:
/**
* 添加学生
* @param student 待添加的学生
* @param callback 回调函数
*/
module.exports.addStudent = function (student, callback) {
fs.readFile(dbPath, function (err, data) {
if (err) {
return callback(err);
}
var students = JSON.parse(data.toString()).students;
student.id = students[students.length - 1].id + 1;// 让id自增长,不重复
students.push(student);
fs.writeFile(dbPath, JSON.stringify({students: students}), function (err) {
if (err) {
return callback(err);
} else {
callback(null);
}
})
});
};
在router.js
文件中处理路由/students/newPage
和/students/new
:
// 渲染学生新增页面
router.get('/students/newPage', function (request, response) {
response.render('add-student.html');
});
// 新增学生
router.post('/students/new', function (request, response) {
var student = request.body;
student.sex = student.sex === '男' ? 1 : 0;
Student.addStudent(student, function (err) {
if (err) {
response.status(500).send('Server Error.')
} else {
response.redirect('/students');
}
})
});
效果如下:
- 编辑学生
在student.js
文件中添加函数来处理修改学生的逻辑:
/**
* 更新指定学生通过id
* @param student
* @param callback
*/
module.exports.updateStudentById = function (student, callback) {
fs.readFile(dbPath, function (err, data) {
if (err) {
return callback(err);
}
// 从文件中查询待更新的学生信息
var students = JSON.parse(data.toString()).students;
var checkedStudent = students.find(function (item) {
return parseInt(item.id) === parseInt(student.id);
});
// 将新属性值覆盖原属性值
for (var key in checkedStudent) {
checkedStudent[key] = student[key];
}
// 将修改后的保存到文件中
fs.writeFile(dbPath, JSON.stringify({students: students}), function (err) {
if (err) {
callback(err);
}
callback(null);
})
});
};
接着在router.js
文件中处理路由/students/editPage
和/students/edit
:
// 渲染学生编辑页面
router.get('/students/editPage', function (request, response) {
var id = request.query.id;
Student.findById(id, function (err, data) {
if (err) {
return response.status(500).send('Server Error.');
}
response.render('edit-student.html', {student: data});
});
});
// 编辑学生
router.post('/students/edit', function (request, response) {
var student = request.body;
student.id = parseInt(student.id);
student.sex = student.sex === '男' ? 1 : 0;
Student.updateStudentById(student, function (err) {
if (err) {
return response.status(500).send('Server Error.');
}
response.redirect('/students');
});
});
效果如下:
- 删除学生
在stduent.js
文件中添加函数来处理学生删除的逻辑:
/**
* 删除指定id的学生
* @param id 待删除学生的id
* @param callback 回调函数
*/
module.exports.deleteStudent = function (id, callback) {
fs.readFile(dbPath, function (err, data) {
if (err) {
callback(err);
}
// 将从数据库中读取的字符串转换成对象,获取学生列表
var students = JSON.parse(data.toString()).students;
// 查找待删除的元素在数组中的下标
var index = students.findIndex(function (item) {
return parseInt(item.id) === parseInt(id);
});
// 删除数组中指定下标的元素
students.splice(index, 1);
// 将删除后的数组又转换成字符串保存到文件中
fs.writeFile(dbPath, JSON.stringify({students: students}), function (err) {
if (err) {
return callback(err);
}
// 成功表示没有报错,则错误对象的值为null
callback(null);
});
})
};
然后在router.js
文件中处理请求/students/delete
:
// 删除学生
router.get('/students/delete', function (request, response) {
// 获取待删除学生的id
var id = request.query.id;
// 调用方法进行删除
Student.deleteStudent(id, function (err) {
if (err) {
return response.status(500).send('Server Error.')
} else {
response.redirect('/students');
}
})
});
MongoDB
下载与安装
关于在Windows系统下安装MongoDB请参考:在Windows系统下安装MongoDB数据库
MongoDB数据库的基本概念
MongoDB数据库特点:
- 可以有多个数据库。MySQL也可以拥有多个数据库。
- 一个数据库中可以有多个集合,在MongoDB中的集合相当于MySQL中的表。
- 一个集合中可以有多个文档,在MongoDB中的文档相当于MySQL中的表记录。
- 文档结构非常灵活,没有任何限制,不需要像MySQL一样先创建数据库、表、设计表结构。
- 在MongoDB中插入数据的时候只需要指定往哪个数据库的哪个集合操作就可以了,由MongoDB来帮你自动完成建库建表的工作。
如下:
{
qq: {
users: [
{name: 张三, age: 13},
{name: 李四, age: 14},
{name: 王五, age: 15},
{name: 赵六, age: 16}
],
products: [
],
...
},
taobao: {
},
baidu: {
}
}
其中如"qq"
、"taobao"
、"baidu"
就是数据库名;如"users"
、"products"
就是"qq"
数据库下的表(也就是集合);如"{name: 张三, age: 13}"
就是集合下的文档(即表中的表记录行)。
在Node中如何操作MongoDB数据库
- 使用官方的
mongodb
包来操作
具体使用请参考:https://github.com/mongodb/node-mongodb-native。但不建议使用。
- 使用第三方的
mongoose
包来操作
mongoose
包是基于MongoDB官方的mongodb
包的进一步封装,推荐使用。
使用第三方的mongoose
包来操作MongoDB数据库
基本使用
首先需要先安装mongoose
包。
npm install mongoose
接着在js文件中引入:
// 引入mongoose
var mongoose = require('mongoose');
// 连接MongoDB数据库
// 其中localhost表示本地连接;test表示数据库名
mongoose.connect('mongodb://localhost/test', {useMongoClient: true});
接着来一个简单的插入操作
// 创建一个模型,就是在设计一个数据库
var Person = mongoose.model('Person', {name: String});
for (let i = 0; i < 10; i++) {
// 实例化一个Person
var person = new Person({name: '张三_' + i});
// 将person保存到mongodb数据库中
// 可以直接调用模型对象的save()方法
person.save(function (err) {
if (err) {
console.log(err);
} else {
console.log('保存成功!');
}
})
}
注意:
- 指定的数据库可以不存在,会自动创建。
设计文档结构(表结构)
字段名称就是表结构中的属性名称,还可以通过required
来添加约束。代码如下:
// 引入mongoose
var mongoose = require('mongoose');
// 连接MongoDB数据库
// 其中localhost表示本地连接;test表示数据库名
mongoose.connect('mongodb://127.0.0.1/test');
// 设计文档结构(表结构)使用mongoose.Schema()方法
var personSchema = mongoose.Schema({
username: {// 字段名
type: String,// 字段类型
require: true// 约束,表示该字段必须有值,相当于MySQL中的not null
},
password: {
type: String,
require: true
},
email: {
type: String
}
});
// 将文档结构发布为模型,mongoose.model()方法就是将一个文档结构发布为Model
// 该方法的第一个参数:传入一个大写名词单数字符串表示数据库名称,其中mongoose会自动把大写名词字符串转换成小写复数的集合名称,如User会变成users
// 该方法的第二个参数:即文档结构
// 该方法的返回值:即模型构造函数
var Person = mongoose.model('Person', personSchema);
// 当我们有了构造函数后,就可以使用这个构造函数对person集合中的数据进行增删改查了
var person = new Person({
username: '张三',
password: '123456',
email: '10086@qq.com'
});
// 可以直接调用save()方法进行保存
person.save(function (err, ret) {
if (err) {
console.log('保存失败!');
} else {
console.log('保存成功!');
console.log(ret);
}
});
新增数据
// 当我们有了构造函数后,就可以使用这个构造函数对person集合中的数据进行增删改查了
var person = new Person({
username: '张三',
password: '123456',
email: '10086@qq.com'
});
// 可以直接调用save()方法进行保存
person.save(function (err, ret) {
if (err) {
console.log('保存失败!');
} else {
console.log('保存成功!');
console.log(ret);
}
});
查询数据
/**
* Model.find(callback)查询所有记录,其中Model就是模型类
* 参数:
* - callback:查询的回调函数,有两个参数:err和ret
* - err:错误对象
* - ret:查询结果集对象,是一个对象
*/
Person.find(function (err, ret) {
if (err) {
console.log('查询失败!');
} else {
console.log(ret);
}
});
/**
* Model.find(filter, callback)按条件进行查询记录,其中Model就是模型类
* 参数:
* - filter:对象,指定查询条件
* - callback:回调函数,有两个参数:err和ret
* - err:错误对象
* - ret:查询结果集对象,是一个对象
*/
Person.find({
username: '张三'
}, function (err, ret) {
if (err) {
console.log('查询失败!');
} else {
console.log(ret);
}
});
删除数据
/**
* Model.remove(filter, callback)按指定条件进行删除
* 参数:
* - filter:对象,指定删除条件
* - callback:删除的回调函数,有两个参数:err和ret
* - err:错误对象
* - ret:返回deletedCount表示被删除记录数
*/
Person.remove({
name: '张三_1'
}, function (err, ret) {
if (err) {
console.log('删除失败!');
} else {
console.log('删除成功!');
console.log(ret);
}
});
/**
* Model.findOneAndRemove(conditions, [options], [callback])根据指定条件删除一条记录
*/
Person.findOneAndRemove({
name: '张三_0'
});
/**
* Model.findByIdAndRemove(id, [options], [callback])根据id删除指定记录
*/
Person.findByIdAndRemove('618d293f47841c8992818388', function (err, doc) {
console.log(doc)
});
更新数据
/**
* Model.update(filter, update, [options], [callback])根据指定条件更新数据
* 参数:
* filter:查询过滤条件
* update:更新的数据
* options:选项对象
* callback:回调函数
*/
Person.update({email: '10086@qq.com'}, {username: '李四'}, function (err, ret) {
if (err) {
console.log('更新失败')
} else {
console.log('更新成功')
}
});
/**
* Model.findOneAndUpdate([filter], [update], [options], [callback])根据指定条件更新一条记录
*/
Person.findOneAndUpdate({username: '李四'}, {email: '10000@163.com'}, function (err, ret) {
console.log(ret);
});
/**
* Model.findByIdAndUpdate(id, update, [options], [callback])根据id进行更新
*/
Person.findByIdAndUpdate('618d2e45b2b4c7aba13bde14', {
username: '王五',
email: '11111@qq.com',
password: '963147'
}, function (err, ret) {
console.log(ret)
});
express+mongodb的CRUD
使用node.js操作mysql数据库
文档:https://www.npmjs.com/package/mysql
安装mysql包:
npm install --save mysql
使用:
// 引入mysql包
var mysql = require('mysql');
// 创建连接
var conn = mysql.createConnection({
host: "localhost",// IP地址
user: "root",// 用户名
password: "root",// 登录密码
database: "test"// 数据库名
});
// 连接数据库
conn.connect();
// 执行操作,无论是查询、新增、删除、更新操作都是query()方法
/**
* conn.query(sql, callback)执行数据库表的增删改查操作
* 参数:
* - sql:SQL语句,可以是select、insert、update、delete语句
* - callback:数据库表操作的回调函数,有三个参数:
* - error:错误对象
* - results:操作结果集
* - fields:数据库表字段信息
*/
// 查询操作
conn.query('select * from `user`', function (error, results, fields) {
if (error) {
// 抛出异常阻止代码往下执行
throw error;
}
console.log(results);// results是查询结果集
console.log(fields);// fields是表字段信息
});
// 更新操作
conn.query('update `user` set username="王五" where id=25', function (error, results) {
if (error) {
// 抛出异常阻止代码往下执行
throw error;
}
console.log(results);// results受影响行信息
});
// 关闭数据库连接
conn.end();