在node上搭建一个mongodb服务器

前言

由于Cloud Studio中每个工作空间只能使用1G的内存,当后台运行进程过多时,如果当前运行的进程需要比较多的内存时,就会造成该进程『killed』(由于可用内存不够导致内存溢出);比如使用npm run devnpm run build时,被kill时就会报一个137的错误,对于node可以通过设置--max-old-space-size来限制nodenpm本身占用的最大内存;但是限制内存后程序自然就运行得慢了。

而像mongodb这种进程在后台运行肯定会占用较多的内存,因此决定将其单独设立到另一个主机空间,做成远程服务器(即不是集成到当前空间和项目中,而是利用ip或网址进行访问,就是调用API接口的形式)进行连接。

准备工作

要使用mongodb光在node项目中引入相关依赖包是不够的,因为那些包只是对mongodb数据库进行连接和操作的!!!所以,首先必须在主机空间里安装mongodb软件。

安装mongodb

  1. 由于Cloud Studio给定的主机是Ubuntu 16.04 x64的,所以需要去Mongodb官网下载中心选择对应系统版本的安装包,然后下载,如:
1
wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-ubuntu1604-3.6.7.tgz
  1. 下载完安装包后,进行解压:
1
tar -xvf mongodb-linux-x86_64-ubuntu1604-3.6.7.tgz

解压后顺便把文件夹名称一改,因为这文件夹名实在是有点长:

1
mv mongodb-linux-x86_64-ubuntu1604-3.6.7 mongodb

现在相当于把mongodb安装在~/path/mongodb文件夹下了。

  1. 添加到环境变量中:

由于studio使用的命令行是zsh,所以需要在~/.zhsrc的末尾添加:

1
2
export MONGODB_HOME="$HOME/path/mongodb"
export PATH="$MONGODB_HOME/bin:$PATH"

添加完后执行更新命令:

1
source .zshrc

然后就可以使用mongodb的命令了。

启动mongodb数据库

启动一个mongodb数据库,需要给定一个存放数据库文件的文件夹路径;比如在~下新建了一个dbdata文件夹,然后指定为数据库文件存放路径并启动mongodb数据库:

1
mongod -dbpath=./dbdata

启动的数据库默认端口是27017,如果要使数据库一直保持运行(后台运行),可以在启动命令的最后添加&即可。

搭建Express服务器

显然,只有数据库是无法完成API接口的;因此需要一个用来接收request,返回response的服务器组件。经过一番查询后,发现在Node.js使用较多的是Express这个服务器框架,看了一下确实比较方便,只需要关心输入输出即可,不需要考虑太多的配置,所以决定搭建一个Express服务器来处理requestresponse

安装依赖

1
npm i express -S

简单的Express服务器

在项目文件夹创建一个app.js文件,然后写一个简单的处理requestresponse的服务器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const express = require('express')
let app = express() // 创建一个express服务器

// 设置路由,根据请求地址的路径来处理request,输出相应的response
app.get('/', (req, res)=>{
res.send('Hello World!')
})

// listen函数用来设置监听端口和ip地址
let server = app.listen('3000', '0.0.0.0', ()=>{
let host = server.address().address
let port = server.address().port

console.log('app listening at http://%s:%s', host, port)
});

上面的代码就相当于建立了一个服务器,这个服务器的地址就是0.0.0.0:3000;然后当使用get方法访问服务器根路径/时,给出的response正文为Hello World!

使用node app.js启动服务器,访问效果如下:

mark

Mongoose

由于node并不能直接连接mongodb服务器进行数据获取和操作,因此需要能够在node下对mongodb服务器进行操作的工具。事实上mongodb官方早就实现了基于Node.js驱动API,只需要在node项目中安装mongodb这个依赖包就可以实现对mongodb服务器的连接和操作;但是由于对数据结构没有限定,使用比较自由,所以觉得另一个基于官方驱动mongoose更符合我的胃口,因为mongooseSchema可以实现对数据的结构和数据类型进行限定。

安装

1
npm i mongoose -S

连接数据库

1
2
3
4
5
6
7
8
9
10
11
12
13
const mongoose = require('mongoose')
const Schema = mongoose.Schema // Schema构造函数
// mongodb连接地址:mongodb://ip:port/database
const url = 'mongodb://0.0.0.0:27017/test'

let db = mongoose.createConnection(url) // 返回数据库的连接对象
db.on('error', (err)=>{ // 监听数据库连接错误事件
throw err
})
db.once('open', function(){ // 监听数据库连接成功事件(once就是监听一次)
console.log('connect success')
db.close() // 关闭数据库连接
})

显然,所有的CRUD操作肯定需要在连接成功事件open)内进行。

Schema、model和document

由于mongodb属于nosql类型数据库,对于数据库中的表(在mongodb中并没有表这一说,相对应的是集合(collection),一个集合并没有数据结构和类型限制,集合内的数据并不需要格式相同);而Schema算是mongoose对于mongodb没有限定集合内数据结构和类型的补充,而model可以看做具有给定Schema集合,而docuement则是model实例,可以看做是该集合内的一条数据

mark

Schema

Schema以键值对的形式来定义数据结构和类型,键名就是字段名称,而值就是类型限制或更加详细的设定;其中可以使用的数据类型有:

  • String
  • Number
  • Date
  • Buffer
  • Boolean
  • MixedSchema.Types.Mixed,实际上就相当于一个Object;这种类型无法对其内部数据类型进行准确限定!
  • ObjectId
  • Array:数组内元素类型可以是Schema或其它数据类型
  • Decimal128
  • Schema:一个已经被定义的Schema可以作为一种类型使用,也就是Schema可以嵌套

P.s:当某个字段的类型为一个对象,且对象的字段全都给定了类型限定,则会被自动转为一个Schema作为该字段的类型!

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
const mongoose = require('mongoose')
const Schema = mongoose.Schema

let user = new Schema({
name: String
}) // 一个已定义的Schema

let group = {
id: Number,
name: String
} // 一个所有字段被限定类型的对象

let habit = {
group: Number,
name: String,
tip: String,
start: Number,
theme: Number,
icon: Number,
day: [Number]
} // 一个所有字段被限定类型的对象

let data = {
uid: Number,
user: user, // Schema作为类型使用
habits: [habit], // 对象作为类型,自动转换成Schema,作为数组元素的类型
group: [group]
}

let dataType = new Schema(data) // 最终的Schema数据结构和类型

model,document

1
2
3
4
5
6
// 按给定数据结构和类型生成Schema,并绑定到指定集合
let schema = Schema(schemaType, {collection: 'info'})
// 按照给定的Schema生成model
let model = dbase.model('', schema)
// 按照给定的model和参数生成一条数据
let data = new model({...})

事实上,Schema只是格式,真正具有CRUD的是modeldocument;而model具有最直接的数据操作。

收尾

简单地来说:mongodb数据库也有了,Express服务器也有了,剩下的就是在相应的路由里由mongoose连接数据库进行CRUD操作,并在response返回相应的数据,这样就构成了一个完整的API服务器了。

参考文档

  1. node+vue+MongoDB从构建项目到服务器部署
  2. 为什么用NPM安装mongodb开启服务不成功?
  3. 使用vue-cli结合express获取mongodb里面的数据 - 明明一颗大白菜 - 博客园
  4. 一个简单的 Express 路由
  5. Express 4.x - API 中文手册
  6. Mongoose 5.0 中文文档