一遍学会vue+node.js+mongoDB全栈流程(1·新手向使用node连接数据库)

1,738 阅读12分钟

在写这篇文章之前,我花了很长时间在网上寻找对新手友好的node.js+mongoDB入门教程。这方面的教程非常多,但是对于一个新手并不友好,这篇文章的目的,就是让一个小小白也能一步步实现使用node+mongoDB创建一个属于自己的服务端,那么我们的全栈之路就从这里开始吧

git地址 https://github.com/foreverway/node-express-mogoDB.git

Node.js 是什么

作为一门服务端语言,node.js使用js的语法,但不代表就可以直接上手使用。当我们打开node.js的官方文档,会发现它着重介绍的是node的特性和api

作为一个称职的新手,我猜你会在十分钟之内关闭这个网页。因为学习是一个渐进的过程,我们通过框架从一个简单的demo入手,慢慢了解node.js会比较好。因为很多特性,包只有在使用的时候才会理解,一开始就学太多陌生的新事物,会让人无所适从 框架很多,一方面我们要快速上手,另一方面也要保留原语言的特性,过度封装的框架,可能反而不利于我们对node的理解,市面上有express,egg.js.next.js等,在这里,我选express入门

使用命令行安装express框架,初始化项目。打开express文件夹,建立一个js文件,比如server.js

在server.js文件中,引用express

const express = require('express) //require是CMD规范,类似es6的import
const app  = express()   执行express返回结果
//启动服务,监听一个端口3000的端口
app.listen(3000,()=>{
console.log('App 正在监听3000的端口')
)})
启动项目 node server  (server.js的后缀可以省略)

但是现在这个端口不会有什么反应,有过数据请求经验的会知道,我们一般会使用get方法请求数据,所以我们写一个关于get方法的定义,接收两个参数,第一个是路径,第二个是一个函数

app.get('/',function(req,res){
    res.send('hello')  //response,请求的时候,响应一个hello字符
})
第一个参数就是别人请求的路径,在这里就是根路径

访问http://localhost:3000/ 这看起来似乎没感觉,那把send输出的值换成一个对象数组

[{name:'朝夕',provience:'广东'},  {name:'xiaomi小明g',provience:'台湾'}]  //重启一次server  node server

我们从后端请求的数组数据就是这样的,这时候你可能会觉得每次改都重启太麻烦了,所以这时候我们换成nodemon(nodemon server)来启动,这样他会自动监听我们的修改。知道了这些,我们可以尝试写更多的接口

app.get('/',function(req,res){
    res.send([{name:'朝夕',provience:'广东'},
            {name:'小明',provience:'台湾'}
])
})
app.get('/shoppingList',function(req,res){
    res.send([{id:'1',provience:'Gift A'},
            {id:'2',provience:'Gift B'},
            {id:'3',provience:'Gift C'}
])
})
app.get('/home',function(req,res){
    res.send('this is my home')
})

这样当我们访问 http://localhost:3000/home 这样当我们访问 http://localhost:3000/shoppingList

托管静态文件

通过上面的方法,我们可以对用户访问网址做出响应,但我们有时候想访问其他页面的内容怎么办呢,这时候我们就需要实现一个路由

app.use(express.static('public')) 我们在server.js中添加这个中间件,他专门用来做静态文件的托管,我们使用这个可以访问到public路径下的文件 新建一个public文件,然后新建一个index.html,随便写点什么

2·访问http://localhost:3000/index.html

3·当然,我们也可以放在其他路径,app.use()的默认路径是根路径,我们也可以自己设置路径,

app.use('/static',express.static('public'))

这时候就需要去http://localhost:3000/static/index.html才可以访问到

处理跨域

我们先在刚刚public创建的index.html文件请求刚刚创建的数据

fetch('http://localhost:3000/shoppingList').then(res=>res.json() 
//将数据转化为json格式
).then(res=>{
    console.log(res)
})

打开http://localhost:3000/static/index.html,在Network可以看到收到的数据

一切看起来很完美,因为我们这里是同域名,端口,协议。不会有跨域的问题 如果在刚刚的步骤,有同学使用了open with live server这个插件,他会基于本地的ip地址,打开 这个网页,顺便 没错,老朋友跨域是不会缺席的,因为这时候我们的域名和协议都改变了,我们应该都知道跨域的解决办法,最常用的就是nginx反向代理和CORS添加允许跨域的请求头 在express中,使用CORS更加简便,有相应的npm包协助我们处理这件事情 cnpm i cors -S

然后在server.js中,引用cors app.use(require('cors')())//直接使用这个模块,回头看,跨域就被解决了..

连接数据库 mongoDB

虽然我们已经可以在前端页面获取node.js生成的数据,但这样每次数据的变动都要手动更改,这样只适合自己纯展示的 mock数据,日常开发,我们的数据都会放在数据库中,数据库不是什么高大上的概念,就我认为 只是一个存放数据的仓库,我们可以通过增删改查语句来查询我们想要的数据 在node中用的比较多的是mongoDB,数据库也有本地的和线上的,当我们没有自己的云服务期的时候,我们只能将数据放在本地 这样就只有自己可以获取到,有自己云服务器的可以放到上面

我们在这里简单讲一下mongoDB,首先自己在官网下载 下载之后,我们需要下载一个在node.js中连接数据库的包 mongoose

npm i mongoose -S

链接数据库 同样的 我们需要在server.js中引入这个包

const mongoose = require('mongoose')
mongoose.connect('mongoose://localhost:27017/ShoppingList')
//第一个参数是数据库的地址,他的格式是mongoDB://开头+数据库的ip地址+端口号默认27017+/
//如果起的是不存在的数据集合,则会自己给你创建
//ShoppingList表明我们连接ShoppingList这个数据集合
在这里我们是本地的数据库所以地址就写localhost或者127.0.0.1

填好之后我们启动,他会报一个错,因为缺少一些参数,我们根据提示,加上

const mongoose = require('mongoose')
mongoose.connect('mongodb://localhost:27017/ShoppingList',
{ useNewUrlParser: true  ,useUnifiedTopology:true} )
链接数据库的代码就是这样

接下来我们需要定义模型(在mongoDB称为集合),也就是对数据库的数据分类,每个模型里面是我们对应的数据 比如我们现在有一个购物列表(shoppingList)的模型,我们需要这样定义

const shoppingList = mongoose.model('ShoppingList',new mongoose.Schema({title:String}))
# 第一个参数为模型的名称,一般首字母需要大写
# 第二个参数是表结构,然后接受一个对象作为参数,比如有title属性,他的值是值的类型,比如String

这样我们就可以先使用了,我们先把刚刚写死的ShoppingList的接口连上数据库

app.get('/shoppingList',async function (req, res) {
    res.send(await ShoppingList.find())
    find()没有限制查询条件,意思是查找所有数据
    这里因为连接数据库是一个异步操作我们这里使用asyncawait能够同步的获取我们数据库得值
})

当然因为数据库里没有数据,所以我们可以临时插入一些数据便于观察, 我们在这个接口下面写一个

ShoppingList.insertMany([{title:'电脑1'},{title:'电脑2'},{title:'电脑3'},])

通过insertMany(插入多条)我们就往数据库插入了后面的数据,保存,看下效果。 如果你多次保存,执行的话会发现,数据越来越多了,因为这个插入语句是会重复执行的 所以我们可以插入之后将他注释掉 访问连接地址,就可以看到我们刚刚插入的数据。多出来的_id表示每一个值的标识是自动生成的,__v表示数据的版本

mongoDB查询

刚刚我们已经对数据库的数据进行过查询,但是很明显工作中需要的很多,比如有分页,有要查询特定条件的值

我们这里改变刚刚的查询条件

app.get('/shoppingList',async function (req, res) {
     // const data = await ShoppingList.find().limit(2)  
    //limit 就像他的意思,限制条数我这里是2条,其实在vscode中,安装好mongoDB的插件,会自动提示find()的方法
 const data = await ShoppingList.find().skip(1).limit(2)  
  //skip 跳过,这里就是显示2.3,跳过1。他们这两个结合就用来做分页
  // const data = await ShoppingList.find().where({
  title:'电脑1'}) 
  //这个就是只查询title等于电脑1的数据
  //sort(_id:1/-1)排序,-1表示倒叙
     res.send( data )

也常常有这种需求,就是查看一个商品的详情,这时候我们可以提供一个专门的接口返回数据

app.get('/shoppingList/:id',async function (req, res) {
    //# :表示后面可以是任意字符
    const data = await ShoppingList.findById(req.params.id)
        //findById这里的id就是我们从url里获取的,req表示客户端请求的参数
        //req.params表示客户端传递过来的所有参数
    res.send( data)
    //res表示服务端相响应的数据
})

就像下面这样

mongoDB编写新增产品和上传的post请求 你刚刚可能注意到了,我们所有的接口都是使用get方法进行的,但有时候我们需要发送一些比较大的数据,不适合通过url发送,这时候就需要使用POST方法 //添加数据到列表接口 //我们刚刚使用代码的insertMany方法插入数据,现在使用post来完成

app.post('/shoppingList',async function (req, res) {
    const data = {}
    //上传一个空对象
    res.send( data)
})

现在去原来的页面请求这条数据 会发现还是访问原来的get接口,因为他们的地址是一样的,这里我们在vscode里下载一个扩展 rest client 他帮助我们使用代码来发起不同类型的http请求 下载完成之后,我们在根目录下新建一个文件,名字随意,但是后缀需要是http 我们先使用get方法 加上我们刚刚的链接
get http://localhost:3000/shoppingList

这时候上面会出现Send Require 我们点一下,在右边就可以看到服务端返回的信息 那我们有多个接口怎么写呢 首先多个接口要用### 分开,然后我们可以定义公共的部分,不用每次都写 像这样,可以看到我们返回回来的结果是空的,因为我们刚刚发送的也是个空对象 //我们知道数据有很多种类型,如果前后端规范不一致 //就会报415的错误,所以在这里我们需要对数据类型进行规范

Content-Type:application/json 记得要紧接着post命令行写

//如果使用axios那样的库就不需要自己加 //我们规定这里发送JSON格式的数据,记得json是双引号 然后使用这个post发送一条数据试试

哎?数据怎么还是没有出现。 因为我们虽然在这里提交,但是服务端并没有接收,我们对刚刚的server.js页面 改写post请求

app.post('/shoppingList',async function (req, res) {
    const data =req.body
    //req.body。了解post请求的会知道,post请求的主体是body,
    //req.body表示客户端提交过来的数据,
    res.send( data)
})

试一下,还是没有返回任何数据,因为express默认没有开启对JSON文件的解析 我们需要在server.js里const app = express()后的任何位置加上 app.use(express.json())) 表示我们允许他解析提交过来的jsop格式的数据

再试一次,发现可以获取到post的数据 做了这么多,只是铺垫,我们回到标题:怎么把post的数据存入数据库 首先排除connect.http,这里只是模拟客户端发送数据,相当于用户上传的部分,这里我们是没办法接触数据库的,只能在服务端进行,也就是我们对应的post请求里 改写post请求

app.post('/shoppingList',async function (req, res) {
    const data = req.body
    const shopping =await ShoppingList.create(data)
    //获取到客户端发送的值之后,创建数据使用create存入ShoppingList集合,记得使用await
    res.send( shopping)
})

在发送试一次 存入数据库成功 设置查询数据库接口为查询所有

//查看列表接口

app.get('/shoppingList',async function (req, res) {
    const data = await ShoppingList.find()
    res.send( data)
})

点击Send request

数据已经存入了数据库 其他类型的请求 一般的,我们使用get获取数据,post发送数据,在修改的时候我们会使用put提交我们的请求 这里就分析一下如何使用put。 其实put和查看详情的接口有一定的相似之处,因为我们都是先通过id等属性 找到某条数据数据,在进行操作

//修改详情接口
app.put('/shoppingList/:id',async function (req, res) {
    //put表示覆盖,patch表示部分修改
    const data = await ShoppingList.findById(req.params.id)
    data.title = req.body.title
    //根据客户端传入的值修改
    await data.save() //保存修改
    res.send( data)
})

然后在connect.http文件,我们写上put接口

PUT {{uri}}shoppingList/5f53bb006e15a80b2c4bdb7c
Content-Type:application/json

{
    "title":"电脑1010"
}
//然后查看产品数据库列表

可以看到,数据库里的值已经修改成功 类似的,我们也可以很容易得到删除的写法

//删除一个数据
app.delete('/shoppingList/:id',async function (req, res) {
    const data = await ShoppingList.deleteOne({id:req.body.id}
    res.send( data)
})
connect.http
DELETE {{uri}}shoppingList/5f538c6054c5512be4876208
Content-Type:application/json
就是这样,执行之后,你同样发现数据库的这条数据已经被删除了

vue项目连接数据库

到现在,我们的基础工作就做到这里,那么在实际项目怎么使用呢

下一篇文章会讲到那些

参考来源

B站:全栈之巅

mongoDB连接数据库的增删盖查