MongoDB
MongoDB
简介
- 官方
MongoDB 是一个文档型数据库,便于开发以及应用扩展
- 百度百科
MongoDB 是一个分布式文件存储数据库,由 C++ 语言编写,旨在为 WEB 提供便捷开发以及应用扩展的数据库解决方案
MongoDB 是介于关系型数据库与非关系型数据库之间的产品,是一款最像关系型数据库功能丰富的非关系型数据库,在 MongoDB中其支持的数据结构非常松散(是类似 JSON 格式的 BSON 格式),同时实现了强大的数据查询语言,几乎实现了关系型数据库查询语言同时支持对数据的索引与聚合等操作
- 总结
MongoDB 是一个分布式的非关系的文档型数据库
特点
- 面向集合存储,容易存储对象类型数据
- 支持查询以及动态查询
- 支持 JAVA/Python/PHP 等多种语言
- 文件存储格式为 BSON(类似于 JSON)
- 支持索引/聚合/事务等
- 支持复制/分片/数据恢复等
安装
传统方式安装
# 安装包下载
wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-5.0.6.tgz
# 解压
tar -zxvf mongodb-linux-x86_64-rhel70-5.0.6.tgz
# 移动家目录
mv mongodb-linux-x86_64-rhel70-5.0.6 /usr/local/mongodb5
mkdir /usr/local/mongodb5/data
mkdir /usr/local/mongodb5/log
cd /usr/local/mongodb5/bin/
./mongod --dbpath=../data --logpath=../logs/mongodb.logs --fork
# 配置环境变量
cat >> /etc/profile << EOF
export MONGODB_HOME=/usr/local/mongodb5
export PATH=$PATH:$MONGODB_HOME/bin
EOF
source /etc/profile
Docker 安装
# 拉取镜像
docker pull mongo:5.0.5
# 运行镜像 由于上述传统方式 27017 已经被占用此处换个端口
docker run -d -p 27018:27017 --name mongodb --hostname mongodb --restart always mongo:5.0.5
# 查看 Docker
docker ps | grep mongodb
# 物理机客户端连接
./mongo --port=27018 172.16.137.128
核心概念
库
在 MongoDB 中库的概念类似于关系型数据库中库的概念,通过不同的库隔离不同的数据同时方便不同的应用拥有自己独立的数据库,每一个库拥有自己的集合和权限,不同的数据库存放在不同的文件中,默认数据库 test 库
集合
在 MongoDB 中集合类似于关系型数据库中的表,一个数据库中可以含有多个集合,集合没有固定的数据结构,意味着你可以添加不同格式和类型的数据存放于集合中
文档
文档类似于关系型数据库中的数据,在 MongoDB 中由(key/value)组合而成的BSON 数据,MongoDB 中的文档不需要设置相同的字段,并且不同的字段可以是不同的数据类型
'''
此时我有个 user 集合
1. {"name": "SR"}
2. {"hobby": ["basketball", "game"]}
可以看出我上述 user 集合中可以产生 name 和 like 字段且其对应的 value 也不同
'''
基本操作
库
查看所有库
# 查看所有库
show databases; show dbs;
- admin: 从权限角度看,这个是 root 用户数据库,如果将用户划分到该数据库中,该用户就会继承所有数据库的权限,一些命令只能位于该库中才能被执行
- local: 位于该库的数据不能被复制,可以用来存储只限于本地数据库中存储的数据
- config: 当 MongoDB 用来分片的时候,config 数据库记录分片的信息
查看当前库
# 查看当前库
db
创建数据库
# 如果不存在则创建 如果存储则切换数据库
use users;
删除数据库
# 删除数据库 在 MongoDB 中可以通过 tab 键进行命令补全
db.dropDatabase();
集合
查询
# 先插入users集合数据做测试
db.users.insert({"name":"SR"})
# 查询集合
show tables;
创建
# 显示创建
db.createCollection('集合名称', [options])
# 创建student表
db.createCollection("student");
options
可选项 | 数据类型 | 作用 |
---|---|---|
capped | 布尔 | (可选)如果为 true,则创建固定集合。固定集合是指有着固定大小的集合,当达到最大值时,它会自动覆盖最早的文档。 当该值为 true 时,必须指定 size 参数。 |
size | 数字 | (可选)为固定集合指定一个最大值,即字节数。 如果 capped 为 true,也需要指定该字段。 |
max | 数字 | (可选)指定固定集合中包含文档的最大数量。 |
删除
# 删除
db.集合名称.drop()
db.student.drop()
文档
插入数据
- 单条插入
# 语法
db.集合名称.insert({})
# 插入数据
db.users.insert({"name":"SR","age":18,"hobby":["sing","game"]})
# 查看数据
db.users.find()
- 多条插入
# 语法
db.集合名称.insertMany(
[文档1,文档2]
{
writeConcern: 1,//写入策略,默认为 1,即要求确认写操作,0 是不要求。
ordered: true //指定是否按顺序写入,默认 true,按顺序写入。
}
)
db.users.insertMany([{"name":"SR1","gender":"male"},{"hobby":["game",]}]);
- 脚本写入
for(let i=0;i<10;i++){
db.users.insert({
"_id":i,"name":"SR"+i,"age":i + 10
})
}
删除数据
# 语法
db.集合名称.remove(
<query>,
{
justOne: <boolean>,
writeConcern: <document>
}
)
# remove 括号中必须跟个空对象
db.users.remove({});
db.users.find();
参数说明:
- query :
可选
删除的文档的条件。 - justOne :
可选
如果设为 true 或 1,则只删除一个文档,如果不设置该参数,或使用默认值 false,则删除所有匹配条件的文档。 - writeConcern :
可选
抛出异常的级别。
# 删除单条数据
# 删除 ID=1的数据
db.users.remove({"_id":1})
# 删除 ID 自动生成的对象
db.users.remove({"_id":ObjectId("6211accd0853afc2088c101e")})
更新数据
# 更新语法
db.集合名称.update(
<query>,
<update>,
{
upsert: <boolean>,
multi: <boolean>,
writeConcern: <document>
}
);
参数说明:
- query : update的查询条件,类似sql update查询内where后面的。
- update : update的对象和一些更新的操作符(如$,$inc...)等,也可以理解为sql update查询内set后面的
- upsert :
可选
,这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入。 - multi :
可选
,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。 - writeConcern :
可选
,抛出异常的级别。
# 先删除在更新 通过 ID 找到匹配文档之后删除
db.users.update({"_id":ObjectId("6211b6042ded1faf9e7a9acd")},{"age":29})
# 保留原始数据直接修改
db.users.update({"_id":9},{$set:{"age":29}})
db.users.find({"_id":9})
db.users.update({"age":18},{$set:{"age":28}});
db.users.find()
# 修改所有
db.users.update({"age":18},{$set:{"age":28}},{"multi":true});
db.users.find()
# 修改插入
db.users.update({"age":100},{"age":99},{"upsert":true})
db.users.find({"age":99})
文档查询
语法
# 查询文档
db.集合名称.find(query, projection)
- query :可选,使用查询操作符指定查询条件
- projection :可选,使用投影操作符指定返回的键(类似于:select name from user)。查询时返回文档中所有键值, 只需省略该参数即可(默认省略)。
如果你需要以易读的方式来读取数据,可以使用 pretty() 方法,语法格式如下:
# 架构化查询 会将过长的数据以便于阅读的格式展示出来
db.集合名称.find().pretty()
# 结构化展示
db.users.find({"age":18}).pretty()
对比语法
操作 | 格式 | 示例 | RDBMS类似语法 |
---|---|---|---|
等于 | { |
db.users.find({"name":"SR"}) | select * from users where name = "SR" |
大于 | { |
db.users.find({age:{$gt:18}}) | select * from users where age > 18 |
小于 | { |
db.users.find({age:{$lt:18}}) | select * from users where age < 18 |
大于等于 | { |
db.users.find({age:{$gte:18}}) | select * from users where age >= 18 |
小于等于 | { |
db.users.find({age:{$lte:18}}) | select * from users where age <= 18 |
不等于 | { |
db.users.find({age:{$ne:18}}) | select * from users where age != 18 |
and
语法
db.集合名称.find({key1:value1, key2:value2,...}).pretty()
类似于 WHERE 语句:WHERE key1=value1 AND key2=value2
示例
db.users.find({"name":"SR","age":{$gte:29}});
# 类似于
select * from users where name = "SR" and age >= 29
or
MongoDB OR 条件语句使用了关键字 $or,语法格式如下:
语法
db.集合名称.find(
{
$or: [
{key1: value1}, {key2:value2}
]
}
).pretty()
类似于 WHERE 语句:WHERE key1=value1 or key2=value2
示例
db.users.find({$or:[{"name":"test"},{"age":29}]});
# 类似于
select * from users where name = "test" or "age" = 29
and/or 联合使用
语法
db.集合名称.find(
{ "age" : {$gt :50 }, $or : [
{"name": "SR"},
{"name": "MongoDB"}
] }
).pretty();
# 类似于
select * from users where name = "SR" and (age=18 or sex = "man")
类似于 WHERE 语句:WHERE key1=value1 and (key2=value2 or key3=value3)
示例
db.users.find(
{ "name" :"SR", "$or" : [{"age":18},{"sex":"man"}] }
).pretty();
数组查询
语法
db.集合名称.find("数组字段":"数组值");
示例
db.users.find({"hobby":"game"});
# $size 按照数组长度查询
db.users.find(
{$or : [ {"hobby":{$size:3}},{"hobby":{$size:5}}]}
).pretty();
模糊查询
db.users.find({"hobby":/si/});
注意:在 mongoDB 中使用正则表达式可以是实现近似模糊查询功能
排序
语法
db.集合名称.find().sort({name:1,age:1})
'''
1. 升序
2. 降序
'''
类似于 order by 字段 1 字段 2
示例
db.users.find().sort({ "_id" :-1, "age" :1 }).pretty();
分页
语法
db.集合名称.find().sort({条件}).skip(start).limit(rows);
类似于 limit start end
示例
db.users.find().sort({ "_id" :-1, "age" :1 }).skip(0).limit(2).pretty();
'''
1. skip 其代表展示的页面 例如想看第一页就输入 0 想看第二页就输入 1
2. limit 其代表展示的条数
'''
总数
语法
db.集合名称.count();
db.集合名称.find({"name":"SR"}).count();
类似于 SQL 语句为: 'select count(id) from ....
示例
db.users.find().count();
db.users.find({"name":"SR"}).count();
去重
语法
db.集合名称.distinct('字段')
类似于 SQL 语句为: 'select distinct name from ....
示例
db.users.distinct("name")
返回指定字段
db.users.find({"age":{$gt:18}},{"name":1,});
索引
说明
索引通常能够极大的提高查询的效率,如果没有索引,MongoDB在读取数据时必须扫描集合中的每个文件并选取那些符合查询条件的记录。这种扫描全集合的查询效率是非常低的,特别在处理大量的数据时,查询可以要花费几十秒甚至几分钟,这对网站的性能是非常致命的。索引是特殊的数据结构,索引存储在一个易于遍历读取的数据集合中,索引是对数据库表中一列或多列的值进行排序的一种结构。
图解
从上图可以看出 MongoDB 索引类似于 MySQL 都是缩小查询范围,之后通过查询范围再次确定真正的数据节点,同时MongoDB在集合层面上定义了索引,并支持对MongoDB集合中的任何字段或文档的子字段进行索引。
操作
查看索引
db.集合名称.getIndexes(keys)
# 查看索引
db.users.getIndexes()
创建索引
db.集合名称.createIndex(keys, options)
db.集合名称.createIndex({"title":1,"description":-1})
说明: 语法中 Key 值为你要创建的索引字段,1 为指定按升序创建索引,如果你想按降序来创建索引指定为 -1 即可。
# 给 name 字段添加升序
db.users.createIndex({"name":1})
createIndex() 接收可选参数,可选参数列表如下:
Parameter | Type | Description |
---|---|---|
background |
Boolean | 建索引过程会阻塞其它数据库操作,background可指定以后台方式创建索引,即增加 "background" 可选参数。 "background" 默认值为false。 |
unique |
Boolean | 建立的索引是否唯一。指定为true创建唯一索引。默认值为false. |
name |
string | 索引的名称。如果未指定,MongoDB的通过连接索引的字段名和排序顺序生成一个索引名称。 |
sparse | Boolean | 对文档中不存在的字段数据不启用索引;这个参数需要特别注意,如果设置为true的话,在索引字段中不会查询出不包含对应字段的文档.。默认值为 false. |
expireAfterSeconds |
integer | 指定一个以秒为单位的数值,完成 TTL设定,设定集合的生存时间。 |
v |
index version | 索引的版本号。默认的索引版本取决于mongod创建索引时运行的版本。 |
weights | document | 索引权重值,数值在 1 到 99,999 之间,表示该索引相对于其他索引字段的得分权重。 |
default_language | string | 对于文本索引,该参数决定了停用词及词干和词器的规则的列表。 默认为英语 |
language_override | string | 对于文本索引,该参数指定了包含在文档中的字段名,语言覆盖默认的language,默认值为 language. |
# name 参数指定索引名称
db.users.createIndex({"name":1},{"name":"name_index"})
删除索引
# 删除指定索引
db.users.dropIndex("name_index")
# 删除所有索引
db.users.dropIndexes()