mongodb基础

NoSQL设计

常见场景及设计方法

内嵌

是指存在关联关系的文档,放在同一文档中,以数组的形式存放。一对多很少,直接内嵌

1
2
3
4
5
6
{
"username": "brain",
"gender": 0,
"roles": ["admin", "user"],
"address": ["address1", "address2"]
}
  • 减少了关联查询
  • 适合与单类需要描述的属性
  • 不经常变化的属性(扩展、嵌套关联)

父引用

是指存在一对多的情况中,放在同一文档中,以数组的形式存放

1
2
3
4
5
6
7
8
9
10
{
"tid": "postId",
"title": "文章标题",
"catalog": "index",
"created": "143876589",
"comments": [
"commentID1",
"commentID2"
]
}

子引用

是指存在一对非常多的情况中,由于数据库文档存放限制,这个时候进行反向引用

1
2
3
4
5
6
7
8
{
"cid": "commentID",
"tid": "postID",
"content": "这是回复的内容",
"isRead": 0,
"isBest": 0,
"status": 1
}

父子引用设计

  • 引用数据内容是否非常多
  • 引用数据量是否非常庞大,而且在增加
  • 数据是否需要单独访问

反范式

范式是指按既定的用法,范式是一种公认的模型或模式。反范式->不走寻常路

1
2
3
4
5
6
7
8
9
10
11
12
{
"tid": "postID",
"title": "文章标题",
"created": "1466542881",
"users": [
{
"uid": "用户ID",
"name": "用户昵称",
"isVIP": 0
}
]
}
  • 是否有提升性能的区间
  • 数据量的变化是否非常庞大,庞大到更新会异常低效
  • 先考虑读写比,才考虑反范式

双向关联的场景及设计原则

启动一个mongoDB

参考

1
2
3
4
5
6
7
8
9
10
11
12
13
# --name mymongo 名字
# -v /mymongo/data:/data/db 数据挂载目录
# -d mongo:4 后台运行
docker run --name mymongo -v /mymongo/data:/data/db -d mongo:4
# 查看容器状态
docker ps
# 查看数据库服务器日志
docker logs mymongo
# mongo express是一个基于网路的mongoDB数据库管理界面
# 下载mongo-express镜像
docker pull mongo-express
# 运行mongo-express
docker run --link mymongo:mongo -p 8081:8081 mongo-express

MongoDB 操作

基本操作

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# 进入容器
docker exec -it mongo /bin/bash
# 登录数据库
# 方法一
mongo -uroot -p123 admin
# 方法二
mongo admin 快捷进入mongo的admin权限库 然后 db.auth('root', '123')
# 方法三
mongo
MongoDB shell version v4.4.2
connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("3c81c8c0-e0c4-4e82-9652-296a090d17c4") }
MongoDB server version: 4.4.2
> db.auth('wsr','123456')
1
> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
test 0.000GB
> use test
switched to db test
> show collections
runoob
user
# 如果进入某一个数据库权限不够,需要在该数据库创建用户
> db.createUser({user:'test',pwd:'123',roles:[{role:'readWrite',db:'admin'}]})
Successfully added user: {
"user" : "test",
"roles" : [
{
"role" : "readWrite",
"db" : "admin"
}
]
}
# 验证权限
> db.auth('test','123')
1
# 切换到具有root权限用户查看所有用户
> show users
# 删除用户
> db.dropUser('test')
# 修改权限
db.updateUser("test",{roles:[ {role:"read",db:"testDB"} ]})
# 修改密码
db.updateUser("test",{pwd:"changepass"});
# 创建数据集
> db.createCollection("goods")
# 添加记录
> db.goods.insert({"name": "每日坚果", "price": "89", "num": "100"})
# 显示goods数据集中所有文档
> db.goods.find()
> db.数据集名.find({"字段名":"条件"})
# 查看article数据集有多少条数据
db.article.count()
# 删除article数据集中所有文档
db.article.remove({})
# 删除当前使用数据库
db.dropDatabase()

mongodb的三个结构: 数据库db/数据集(集合)collection/文档xxx, 分别对应着mysql中的数据库/数据表/数据记录

备份和恢复

1
2
3
4
5
6
7
8
9
10
11
12
13
# 备份数据库到容器的一个目录
docker exec -it mongo mongodump -h localhost -u root -p password -o /tmp/test
# /tmp/test 在容器内部
# 把容器内部的数据拷贝到宿主机
# 在宿主机上执行
# docker cp 容器名:要拷贝的文件在容器里面的路径 要拷贝到宿主机的相应路径
docker cp 容器名:/tmp/test /tmp/test
# 恢复
docker exec -it mongo mongorestore -h localhost -u root -p oassword --dir /tmp/test
# 把宿主机的文件目录拷贝到镜像
# 在宿主机里面执行
# docker cp 要拷贝的文件路径 容器名:要拷贝到容器里面对应的路径
docker cp /tmp/test 容器名:/tmp/test

Mongoose

分类 Mysql MongDB Mongoose
1 数据库实例 MongDB实例 Mongoose
2 模式(schema) 数据库(database) mongoose
3 表(table) 集合(collection) 模板(Schema)模型(Model)
4 行(table) 文档(document) 实例(instance)
5 Primary key Object(_id) Object(_id)
6 表字段Column Field Field

官网

1
2
npm install -S mongoose
npm install -S saslprep

例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const mongoose = require('mongoose')
// 使用新的服务器发现和监视引擎,请将选项{ useUnifiedTopology:true }传递给mongoclient构造函数,使用 userNewUrlParser: true 解决当前URL解析器被废弃警告
mongoose.connect('mongodb://用户名:密码@ip:端口/数据库名称', { userNewUrlParser: true, useUnifiedTopology: true })

// 链接到 user 集合
const User = mongoose.model('users', {name: String, age: Number, email: String})

const wsr = new User({
name: 'wsr',
age: 23,
email: 'wangshrl@163.com'
})

// 插入到数据库
wsr.save().then(()=>{
console.log('save ok!')
})

核心概念(Schema、Model)

Schema: 一种以文件形式存储的数据库模型骨架,不具备数据库的操作能力。每一个 Schema 对应 MongoDB 中的一个集合(collection)。Schema 中定义了集合中文档(document)的样式。
Model: 由Schema发布生成的模型,具有抽象属性和数据库操作能力
Entity: 由Model创建的实例,也能操作数据库

安装 & 初始化配置

  • 配置数据库用户名密码,ip,端口,数据库名
  • config/index.js*
1
2
3
4
5
const DB_URL = 'mongodb://wsr:123456@49.232.90.151:10050/test'

export default{
DB_URL
}
  • 创建连接
  • config/DBHelper.js*
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
import mongoose from 'mongoose'
import config from './index'

// 创建连接
mongoose.connect(config.DB_URL, {
useNewUrlParser: true,
useUnifiedTopology: true
})

// 连接成功
mongoose.connection.on('connected', ()=>{
console.log('mongoose is connected with' + config.DB_URL)
})

// 连接异常
mongoose.connection.on('error', ()=>{
console.log('mongoose is connected with' + config.DB_URL+ 'is error')
})

// 断开连接
mongoose.connection.on('disconnected', ()=>{
console.log('mongoose is disconnected with' + config.DB_URL)
})

export default mongoose
  • 测试数据库连接是否成功
  • model/test.js*
1
2
3
4
5
6
7
8
9
10
11
12
import mongoose from '../config/DBHelper'

const Schema = mongoose.Schema

const TestSchema = new Schema({
'name': { type: String },
'age': { type: Number }
})

const TestModel = mongoose.model('users', TestSchema)

export default TestModel
  • 数据库增删改查操作
  • model/demo.js*
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
31
32
33
34
35
36
37
import User from './test'

// 增
const insertMothod = async () => {
const data = new User({
name: 'wsr',
age: 18
})
const result = await data.save()
console.log(result)
}

insertMothod()

// 查
const findMothod = async () => {
const result = await User.find()
console.log(result)
}

findMothod()

// 改
const updateMothod= async () => {
const result = await User.updateOne({name: 'wsr'}, {age: 20})
console.log(result)
}

updateMothod()

// 删
const deleteMothod= async () => {
const result = await User.deleteOne({name: 'wsr'})
console.log(result)
}

deleteMothod()