mangoDB

NoSQL

不仅仅是 SQL,即非关系型数据库.

分类

  1. 键值数据库(Redis,Flare)

拥有极高的读写性能,用于处理大量数据的高访问负载,例如日志系统.

  1. 文档型数据库(mangoDB,CouchDB)

满足海量的访问和存储,同时对字段要求不严格,可以随意增删改,适用于网络应用.

  1. 列存储型数据库(Cassandra,Hbase)

查找快,扩展性强,适合用作分布式文件存储系统.(大数据)

  1. 图存储型数据库(InfoGrid,Heo4J)

利用图结构的相关算法来存储实体之间的关系信息,适用于构建社交网络和推荐系统的关系图谱.

选择

既然 NoSQL 数据库有这么多的优势,那它是否可以直接取代天系型数据库?
NoSQL 并不能完全取代关系型数据库,NoSQL 主要被用来处理大量且多元数据的存储及运算问题。在这样的特性差异下,我们该如何选择合适的数据库以解决数据存储与处理问题呢?这里提供以下几点作为判断依据。

  1. 数据模型的关联性要求

NoSQL 适合模型关联性比较低的应用。因此:
·如果需要多表关联,则更适合用 RDB
·如果对象实体关联少,则更适合用 NoSQL 数据库.
其中 MongoDB 可以支持复杂度相对高的数据结构,能够将相关联的数据以文档的方式嵌入,从而减少数据之间的关联操作

  1. 数据库的性能要求

如果数据量多切访问速度至关重要,那么使用 NoSQL 数据库可能是比较合适的。NoSQL 数据库能通过数据的分布存储大幅地提供存储性能。

  1. 数据的一致性要求

NoSQL 数据库有一个缺点:其在事务处理与一致性方面无法与 RDB 相提并论。
因此,NoSQL 数据库很难同时满足强一致性与高并发性。如果应用对性能有高要求,则 NoSQL 数据库只能做到数据最终一致。

  1. 数据的可用性要求

考虑到数据不可用可能会造成风险,NoSQL 数据库提供了强大的数据可用性(在一些需要快速反馈信息给使用者的应用中,响应延迟也算某种程度的高可用)。
一个项目并非只选择一种数据库,可以将其拆开设计,将需要 RDB 特性的放到 RDB 中管理,而其它数据放到 NoSQL 中管理。

安装 MongoDB

1
2
brew tap mongodb/brew
brew install mongodb-community@4.4

然后按照提示修改环境变量,使用source命令重启.

英特尔处理器 苹果 M1 处理器
配置文件 /usr/local/etc/mongod.conf /opt/homebrew/etc/mongod.conf
log directory(log 目录) /usr/local/var/log/mongodb /opt/homebrew/var/log/mongodb
data directory(data 目录) /usr/local/var/mongodb /opt/homebrew/var/mongodb

启动

1
2
3
4
5
brew services start mongodb-community@4.4
// 停止
brew services stop mongodb-community@4.4
// 查看后台服务列表
brew services list

mongo shell

mongoDB 退出的 shell 命令,进入方法,先启动 MongoDB 服务,再输入mongo.
shell 中支持基本的 js 语法.

端口号

默认链接 27017 端口,如果要修改

1
2
3
mongo --prot 27018
// 连接远程主机
mongo --host mongodb0.example.com:28015

常用操作

查看数据库: show dbs
当前数据库: db
切换/创建数据库: use <name>
查看集合: show collections
清空数据库: db dropDatabase()
创建集合: db.xxx.insert({})
查询集合: db.xxx.find()
删除集合: db.xxx.drop()

文档

MongoDB 将数据存储为 BSON 文档.

字段

文档对字段名称有以下限制:

  • 字段名称_id 保留用作主键;它的值在集合中必须是唯一的,不可变的,并且可以是数组以外的任何类型.
  • 字段名称不能包含空字符。

_id 字段

在 MongoDB 中,存储在集合中的每个文档都需要一个唯一的_id字段作为主键。如果插入的文档省略_id字段,则 MongoDB 驱动程序会自动为_id字段生成 Objectld。
id 字段具有以下行为和约束:

  • 默认情况下,MongoDB 在创建集合时会在_id字段上创建唯一索引。
  • _id字段始终是文档中的第一个字段
  • _id字段可以包含任何 BSON 数据类型的值,而不是数组。

创建文档

  • db.xxx.insertOne(): 插入一个,返回 id
  • db.xxx.insertMany(): 插入多个,返回 id
  • db.xxx.insert(): 插入任意个,返回是否成功

查询文档

  • db.xxx.find(query, projection)
    • query,可选,指定查询条件
    • projection,可选,使用投影操作符指定返回的键.
    • $or或查询,匹配一个或多个条件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 条件查询
db.xxx.find({
status: "A", //查询条件为A的所有
});
db.xxx.find(
{},
{
item: 1, //1 表示查询item,0表示不包括item
qty: 1,
}
);
// 或查询
db.xxx.find({
$or: [
(status: "A"),
{
qty: { $lt: 30 }, // qty小于30
},
],
});
  • db.xxx.findOne()

类型检查

BSON 类型为 Nul(类型编号 10):

1
db.xxx.find({ item: { $type: 10 } });

存在检查

查询匹配不包含 item 的文档:

1
db.xxx.find({ item: { $exists: false } });

更新文档

  • db.xxx.updateOne(<filter>, <update>, <options>)
  • db.xxx.updateMany(<filter>, <update>, <options>)
  • db.xxx.replaceOne(<filter>, <update>, <options>)

可以指定更新文档的条件或过滤器.

1
2
3
4
5
// 将age小于18 的文档中status更新为reject
db.xxx.updateMany({
{age: { $lt: 18 },
{$set: {stastus: 'reject'}}
})

替换文档

1
2
3
4
db.xxx.replaceOne(
{item: 'paper'},
{item: 'paper', instock: {qty: 60}
)

删除文档

  • db.xxx.deleteMany()
  • db.xxx.deleteOne(): 仅删除一个符合条件的文档

数据库的操作

  • 导出数据库 ./mongoexport –port [port] –db test –collection users –out export.json
  • 导入数据库 ./mongoimport -h 120.79.229.197:27-17 -d test -c scenics –file=./export.json

Node 中使用 MongoDB

1
2
//安装mongo,这是项目中使用的为node准备的工具
npm i mongo -D
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
const { MongoClient } = require("mongodb");

const client = new MongoClient("mongodb://127.0.0.1:27017"); // 连接本地mongo客户端

async function run() {
try {
// 开始连接
await client.connect();
// 操作数据库
const testDB = client.db("test");
// 通过数据库获取集合
const userCollection = testDB.collection("users");
// 增加
// const ret = await userCollection.insertOne({
// name: 'Jim',
// age: 12
// })
// console.log(ret);

// 查询参数
const ret = await userCollection.find();
console.log("ret: ", await ret.toArray()); // ret.toArray()返回promise所以await
} catch (error) {
console.log("连接失败", err);
} finally {
// 断开连接
await client.close();
}
}

run();

删除_id 的文档

1
2
3
4
5
6
const { ObjectId } = require("mongodb");
// 删除
const ret = await userCollection.deleteOne({
_id: ObjectId("636b5886e7de417db38a5610"),
});
console.log(ret);