标题# Mongodb
视频地址:https://www.bilibili.com/video/BV1vL4y1J7i3?from=search&seid=15714205798348584923&spm_id_from=333.337.0.0
1.安装(默认端口27017)
在这里插入图片描述
1.1 传统方式
./mongod --port 27017 --dbpath …/data --logpath …/logs/mongo.log
–frok 代表后台运行
–bing_id=0.0.0.0开启远程连接服务
1.2 docker安装
1.拉取镜像
docker pull mongo
2.运行镜像
docker run -d --name mongo -p 27017:27017 mongo:5.0.5
3.进入mongo容器
docker exec -it mongo bash
4.启动mongodb服务
mongo
2.核心概念
库
==mongodb中的库就类似于传统关系型数据库中库的概念,用来通过不同库隔离不同应用数据。==mongodb中可以建立多个数据库。每一个库都有自己的集合社权限,不同的数据库也放置在不同的文件中。默认的数据库为"test",数据库存储在启动指定的data目录中。
集合
集合就是MongoDB文档组,类似于RDBMS(关系数据库管理系统:RelationalDatabase Management System)中的表钓概念。
集合存在于数据库中,一个库中可以创建多个集合。每个集合没有固定的结构,这意味着你在对集合可以插入不同格式和类型的数据,但通常情况下我们插入集合的数据都会有一定的关联性。
文档
文档集合中一条条记录,是一组键值(key-value)对(即BSON)。MongoDB的文档不需要设置相同的字段,并且相同的字段不需要相同的数据类型,这与关系型数据库有很大的区别,也是MongoDB非常突出的特点。
一个文档的简单列子
{“site”:“www.baidu.com”,“name”:“张三”}
3.基本操作
库的操作
3.1、查看数据库
show databases|show dbs
> show dbs
admin 0.000GB
chihiro 0.024GB
config 0.000GB
local 0.000GB
(当库中没有数据时,默认时不会显示的)
注意:
admin:从权限的角度来看,这是"root"数据库。要是将一个用户添加到这个数据库,这个用户自动继承所有数据库的权限。一些特定的服务器端命令也只能从这个数据库运行,比如列出所有的数据库或者关闭服务器。
local:这个数据永远不会被复制,可以用来存储限于本地单台服务器的任意集合
config :当Mongo用于分片设置时, config数据库在内部使用,用于保存分片的相关信息。
3.2、创建数据库
use 库名
use chihiro
3.3、查看当前库
db
3.4、删除数据库
> db.dropDatabase()
{ "ok" : 1 }
默认的数据库中存在一个test库
集合的操作
3.5、查看集合
show tables|show collections
> show tables
db1
db2
3.6、创建集合
注意:capped 和 size使用时需要同时出现
3.7、删除集合
> db.db2.drop()
true
-- db.集合名.drop()
文档的操作(增删改)
数据库中的最小单元
3.8、插入文档
3.9、查询所有文档
3.10、删除文档
删除所有文档
3.11、更新文档
默认multi为false只会更新第一条
加上参数multi改为true就可以更新满足条件的所有文档
加上参数upsert即可在未查询满足条件后向文档插入一条新的文档
文档查询
3.12、基础查询
年龄大于22
> db.db1.find({age:{$gt:22}})
{ "_id" : ObjectId("62459a628e6dbfd49795a44d"), "name" : "pengshen2", "age" : 33 }
{ "_id" : ObjectId("62459a628e6dbfd49795a44e"), "name" : "pengshen3", "age" : 33 }
年龄小于22
> db.db1.find({age:{$lt:22}})
{ "_id" : ObjectId("6245aa179c5fe7700d584ae9"), "name" : "xiaoliu", "age" : 11, "likes" : [ "boot", "ppol" ] }
{ "_id" : ObjectId("624660c0f2e309e390764e30"), "name" : 222, "age" : 11 }
年龄大于等于22
> db.db1.find({age:{$gte:22}})
{ "_id" : ObjectId("62459a628e6dbfd49795a44d"), "name" : "pengshen2", "age" : 33 }
{ "_id" : ObjectId("62459a628e6dbfd49795a44e"), "name" : "pengshen3", "age" : 33 }
年龄不等于33
> db.db1.find({age:{$ne:33}})
{ "_id" : ObjectId("62459a628e6dbfd49795a44c"), "name" : "pengshen1", "age" : 22 }
3.13、连接查询(and、or)
and连接查询
and同时有两个相同的字段时后面的条件会覆盖前面的
> db.db1.find({age:22,age:11})
{ "_id" : ObjectId("6245aa179c5fe7700d584ae9"), "name" : "xiaoliu", "age" : 11, "likes" : [ "boot", "ppol" ] }
{ "_id" : ObjectId("624660c0f2e309e390764e30"), "name" : 222, "age" : 11 }
or连接查询(用$or标识)
and和or联合查询
> db.db1.find({age:33,$or:[{name:'pengshen3'},{name:'pengshen4'}]})
{ "_id" : ObjectId("62459a628e6dbfd49795a44e"), "name" : "pengshen3", "age" : 33 }
{ "_id" : ObjectId("62459a628e6dbfd49795a44f"), "name" : "pengshen4", "age" : 33 }
查询年龄等于=33并且name=pengshen3或者name=pengshen2
3.14、数组查询
-- db.集合名称.insert({name:'xiaoliu',age:11,likes:['boot','ppol']})
-- 数组查询
db.db1.find({likes:'boot'})
-- 数组根据长度查询
db.db1.find({likes:{$size:2}})
3.15、模糊查询
-- 模糊查询时根据正则表达式来查询
-- 查询数组中含有oo的元素
db.db1.find({likes:/oo/})
{ "_id" : ObjectId("6245aa179c5fe7700d584ae9"), "name" : "xiaoliu", "age" : 11, "likes" : [ "boot", "ppol" ] }
3.16、排序
-- db.集合名称.find(().sort( {name : 1 , age :1}),1 升序-1降序
> db.db2.find().sort({age:-1})
{ "_id" : 999999, "age" : 999999 }
{ "_id" : 999998, "age" : 999998 }
{ "_id" : 999997, "age" : 999997 }
{ "_id" : 999996, "age" : 999996 }
{ "_id" : 999995, "age" : 999995 }
{ "_id" : 999994, "age" : 999994 }
3.17、分页
--> db.集合名称.find().sort({条件}).skip(start).limit( rows);
db.db2.find().sort({age:-1}).skip(0).limit(4)
{ "_id" : 10, "age" : 10 }
{ "_id" : 9, "age" : 9 }
{ "_id" : 8, "age" : 8 }
{ "_id" : 7, "age" : 7 }
3.18、总条数
-- > db.集合名称.count();
-- > db.集合名称.find({"name":"编程不良人"}).count() ;
db.db2.find().count()
999999
> db.db2.find({age:22}).count()
1
类似于SQL语句为: 'select count(id) from ....'去重
3.19、去重
> db.集合名称.distinct('字段')
> db.db1.distinct("age")
[ 11, 22, 33 ]
3.20、返回指定字段
> db.集合名称.find({条件}, {name : 1 , age :1})
-参数2:1返回0不返回`注意:1和8不能同时使用`
> db.db1.find({},{name:1})
{ "_id" : ObjectId("62459a628e6dbfd49795a44c"), "name" : "pengshen1" }
{ "_id" : ObjectId("62459a628e6dbfd49795a44d"), "name" : "pengshen2" }
{ "_id" : ObjectId("62459a628e6dbfd49795a44e"), "name" : "pengshen3" }
{ "_id" : ObjectId("62459a628e6dbfd49795a44f"), "name" : "pengshen4" }
{ "_id" : ObjectId("62459a628e6dbfd49795a450"), "name" : "pengshen5" }
4.$type
stype操作符是基于BSON类型来检索集合中匹配的数据类型,并返回结果。MongoDB中可以使用的类型如下表所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fVV0me43-1648957981230)(C:\Users\dell\Desktop\学习路线笔记\mongodb\images\image-20220401101614805.png)]
-- 查询name未double类型的
> db.db1.find({name:{$type:'double'}})
{ "_id" : ObjectId("624660c0f2e309e390764e30"), "name" : 222, "age" : 11 }
-- 或者db.db1.find({name:{$type:1}})
-- 查询name为String类型的
> db.db1.find({name:{$type:"string"}})
-- 查询likes为数组类型的
> db.db1.find({likes:{$type:'array'}})
5.索引
索引通常能够极大的提高查询的效率,如果没有索引,MongoDB在读取数据时必须扫描集合中的每个文件并选取那些符合查询条件的记录。这种扫描全集合的查询效率是非常低的,特别在处理大量的数据时,查询可以要花费几十秒甚至几分钟,这对网站的性能是非常致命的。索引是特殊的数据结构,索引存储在一个易于遍历读取的数据集合中,索引是对数据库表中一列或多列的值进行排序的一种结构。
原理
5.1、创建索引
> db.集合名称.createIndex(keys,options)
> db.集合名称.createIndex( {"title" :1 , "description" :-1})
-- 说明:语法中Key值为你要创建的索引字段,1为指定按升序创建索引,如果你想按降序来创建索引指定为-1 即可。
> db.db1.createIndex({name:1},{name:'name_index',expireAfterSeconds:10})
{
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"createdCollectionAutomatically" : false,
"ok" : 1
}
-- 创建复合索引,复合索引不支持expireAfterSeconds
> db.db1.createIndex({name:1,age:-1},{name:'name_age_index'})
{
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"createdCollectionAutomatically" : false,
"ok" : 1
}
createIndex内可以携带参数
5.2、查看索引
> db.db1.getIndexes()
[ { "v" : 2, "key" : { "_id" : 1 }, "name" : "_id_" } ]
-- 无论如何都存在默认索引—_id
5.3、查看索引大小
> db.db1.totalIndexSize()
36864
-- 返回的是一个字节数
5.4、删除所有索引
> db.db1.dropIndexes()
{
"nIndexesWas" : 1,
"msg" : "non-_id indexes dropped for collection",
"ok" : 1
}
5.5、删除指定索引
> db.db1.dropIndex('name_index')
{ "nIndexesWas" : 2, "ok" : 1 }
5.6复合索引
6.聚合查询
MongoDB中聚合(aggregate)主要用于处理数据(诸如统计平均值,求和等),并返回计算后的数据结果。有点类似sQL语句中的count(*)。
-- 求和name总数 _id是标识字段,必须加上
> db.db1.aggregate([{$group:{_id:'name','age':{$sum:1}}}])
{ "_id" : "name", "age" : 13 }
-- 求age平均值
> db.db1.aggregate([{$group:{_id:'name','age':{$avg:'$age'}}}])
{ "_id" : "name", "age" : 28.76923076923077 }
-- 将查询的添加到一个数组
> db.db1.aggregate([{$group:{_id:'name','age':{$push:'$age'}}}])
{ "_id" : "name", "age" : [ 22, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 11, 11 ] }
-- 将查询的添加到一个数组且元素不可重复
> db.db1.aggregate([{$group:{_id:'name','age':{$addToSet:'$age'}}}])
{ "_id" : "name", "age" : [ 11, 33, 22 ] }
-- 查询第一个
> db.db1.aggregate([{$group:{_id:'name','age':{$first:'$age'}}}])
{ "_id" : "name", "age" : 22 }
-- c
> db.db1.aggregate([{$group:{_id:'name','age':{$last:'$age'}}}])
{ "_id" : "name", "age" : 11 }
7.navicat可视化界面
远程连接时需要注意
1.默认解压安装的mongodb时没有开启远程服务的需要设置–bind_id=0.0.0.0开启
2.docker运行的mongodb默认时开启远程服务的
8.springboot整合
1.导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>
spring-boot-starter-data-mongodb
</artifactId>
</dependency>
2.编写配置
# 默认无安全验证
spring.data.mongodb.uri=mongodb://1.14.17.152:27017/chihiro
# 又安全验证时
#spring.data.mongodb.host=1.14.17.152
#spring.data.mongodb.port=27017
#spring.data.mongodb.username=root
#spring.data.mongodb.password=***
8.1操作集合
集合创建
boolean db21 = mongoTemplate.collectionExists("db2");
if (db21 == false) {
mongoTemplate.createCollection("db2");
}
集合删除
mongoTemplate.dropCollection("db2");
8.2文档添加
mongoTemplate.insert(new User(4, "小wangb", 22, new Date()), "db1");
mongoTemplate.save(new User(1,"小米",22,new Date()));
mongoTemplate.insert(Arrays.asList(new User(2, "小号", 11, new Date()),new User(3, "chiwan", 99, new Date())), User.class);
--insert 可以批量插入数据,重复id会报错
--save不可以批量插入数据,重复id不会报错
8.3文档查询
//根据id查询
mongoTemplate.findById(1, User.class);
//查询所有
mongoTemplate.findAll(User.class);
//等值查询
mongoTemplate.find(Query.query(Criteria.where("name").is("小红")), User.class);
//<,>,>=,<=
mongoTemplate.find(Query.query(Criteria.where("age").lt(33)), User.class);
//and查询
mongoTemplate.find(Query.query(Criteria.where("name").is("小号").and("age").is(11)), User.class);
//or查询
Criteria criteria = new Criteria();
criteria.orOperator(Criteria.where("name").is("小号"), Criteria.where("name").is("小红"));
mongoTemplate.find(Query.query(criteria), User.class);
//and or 查询
mongoTemplate.find(Query.query(Criteria.where("age").is(22).orOperator(Criteria.where("name").is("小红"), criteria.where("name").is("小wangb"))), User.class);
//排序
mongoTemplate.find(new Query().with(Sort.by(Sort.Order.desc("age"))), User.class);
//分页
mongoTemplate.find(new Query().with(Sort.by(Sort.Order.desc("age"))).skip(3).limit(2), User.class);
//总条数
mongoTemplate.count(new Query(), User.class);
//去重
mongoTemplate.findDistinct(new Query(), "age", User.class, int.class);
//传统采用Json格式查询
mongoTemplate.find(new BasicQuery("{$or:[{age:22},{age:99}]}", "{name:0}"), User.class);
8.3文档更新
//更新第一条
Query query = new Query(Criteria.where("age").is(44));
mongoTemplate.updateFirst(query, new Update().set("age", 33).set("name", "小王八"), User.class);
//更新批量
mongoTemplate.updateMulti(query, new Update().set("age", 11), User.class);
//更新插入
UpdateResult age = mongoTemplate.upsert(query, new Update().set("age", 44), User.class);
System.out.println(age.getModifiedCount());//修改条数
System.out.println(age.getMatchedCount());//匹配条数
System.out.println(age.getUpsertedId());//插入id
8.5文档删除
//条件删除
mongoTemplate.remove(new Query(Criteria.where("age").is(44)), User.class);
//删除所有
mongoTemplate.remove(new Query(), User.class);
9.副本集(Replica set)
官方地址:https://docs.mongodb.com/manual/replication/
MongoDB副本集(Replica Set)是有自动故障恢复功能的主从集群,有一个Primary节点和一个或多个Secondary节点组成。副本集没有固定的主节点,当主节点发生故障时整个集群会选举一个主节点为系统提供服务以保证系统的高可用。
9.1Automatic Failover
自动故障转移机制:当主节点未与集合的其他成员通信超过配置的选举超时时间(默认为10秒)时,合格的辅助节点将调用选举以将自己提名为新的主节点。集群尝试完成新主节点的选举并恢复正常操作。
9.2搭建副本集
1.创建数据目录
mkdir -p rep1/data1
mkdir -p rep1/data2
mkdir -p rep1/data3
2.搭建副本集
./mongod --port 27017 --dbpath ../rep1/data1 --bind_ip 0.0.0.0 --replSet myreplace/[1.14.17.152:27018,1.14.17.152:27019]
./mongod --port 27018 --dbpath ../rep1/data2 --bind_ip 0.0.0.0 --replSet myreplace/[1.14.17.152:27017,1.14.17.152:27019]
./mongod --port 27019 --dbpath ../rep1/data3 --bind_ip 0.0.0.0 --replSet myreplace/[1.14.17.152:27018,1.14.17.152:27017]
3.配置副本集,连接任意节点
use admin
初始化副本集
config={_id:"myreplace",members:[{_id:0,host:"1.14.17.152:27017"},{_id:1,host:"1.14.17.152:27018"},{_id:2,host:"1.14.17.152:27019"}]}
//rs.initiate(config) 初始化配置
设置客户端可以临时访问
rs.secondaryOk()
9.3 idea和navicat连接
1.navicat连接
2.idea连接
修改配置文件即可
spring.data.mongodb.uri=mongodb://1.14.17.152:27017,1.14.17.152:27018,1.14.17.152:27019/chihiro
10.分片集群(sharing cluster)
官方地址:https://docs.mongodb.com/manual/sharding/
分片(sharding)是指将数据拆分,将其分散存在不同机器的过程,有时也用分区(partitioning)来表示这个概念,==将数据分散在不同的机器上,==不需要功能强大的大型计算机就能存储更多的数据,处理更大的负载。
分片目的是通过分片能够增加更多机器来应对不断的增加负载和数据,还不影响应用运行。
MongoDB支持自动分片,可以摆脱手动分片的管理困扰,集群自动切分数据做负载均衡。MongoDB分片的基本思想就是将集合拆分成多个块,这些快分散在若干个片里,每个片只负责总数据的一部分,应用程序不必知道哪些片对应哪些数据,甚至不需要知道数据拆分了,所以在分片之前会运行一个路由进程,mongos进程,这个路由器知道所有的数据存放位置,应用只需要直接与mongos交互即可。mongos自动将请求转到相应的片上获取数据,从应用角度看分不分片没有什么区别。
10.1集群搭建
我这里只搭建了两个集群和两个configserver
1.集群规划
- Shard server 1:27817 --集群端口
- shard Repl 1:27018
- Shard server 1:27819
- shard Repl 1:27020
- Config Server : 27021 --configserver端口
- Config Server : 27022
- Route Process : 27023 --路由端口
#2.进入安装的bin目录创建数据目录
- mkdir -p ../cluster/shard/s0
- mkdir -p ../cluster/shard/s0-rep1
- mkdir -p ../cluster/shard/s1
- mkdir -p ../cluster/shard/s1-rep1
- mkdir -p ../cluster/shard/config1 --config文件
- mkdir -p ../cluster/shard/config2
#3.启动4个shard服务
#启动r0
./mongod --port 27017 --dbpath ../cluster/shard/s0 --bind_ip 0.0.0.0 --shardsvr --replSet r0/1.14.17.152:27018
./mongod --port 27018 --dbpath ../cluster/shard/s0-rep1 --bind_ip 0.0.0.0 --shardsvr --replSet r0/1.14.17.152:27017
# 1.登录任意节点
# 2. use admin
# 3.执行
config={_id:"r0",members:[{_id:0,host:"1.14.17.152:27017"},{_id:1,host:"1.14.17.152:27018"}]}
rs.initiate(config) 初始化配置
#启动r1
./mongod --port 27019 --dbpath ../cluster/shard/s1 --bind_ip 0.0.0.0 --shardsvr --replSet r1/1.14.17.152:27020
./mongod --port 27020 --dbpath ../cluster/shard/s1-rep1 --bind_ip 0.0.0.0 --shardsvr --replSet r1/1.14.17.152:27019
# 1.登录任意节点
# 2. use admin
# 3.执行
config={_id:"r1",members:[{_id:0,host:"1.14.17.152:27019"},{_id:1,host:"1.14.17.152:27020"}]}
rs.initiate(config) 初始化配置
#4.启动2个config服务
./mongod --port 27021 --dbpath ../cluster/shard/config1 --bind_ip 0.0.0.0 --replSet config/1.14.17.152:27022 --configsvr
./mongod --port 27022 --dbpath ../cluster/shard/config2 --bind_ip 0.0.0.0 --replSet config/1.14.17.152:27021 --configsvr
#5.初始化 config server副本集-`
#登录任意节点congfig server'>
1.use admin
#2.在admin中执行
config = {_id : "config",configsvr: true,members: [{_id :0 , host : "1.14.17.152:27022"},{_id :1, host: "1.14.17.152:27021"}]}
rs.initiate(config);1/初始化副本集配置
#6.启动mongos路由服务
./mongos --port 27023 --configdb config/1.14.17.152:27021,1.14.17.152:27022 --bind_ip 0.0.0.0
#7.登录mongos服务
>1.登录 ./mongo --port 27023
>2.use admin
>3.添加分片信息
db.runCommand({ addshard:"r0/1.14.17.152:27017","allowLocal":true});
db.runCommand({ addshard:"r1/1.14.17.152:27019","allowLocal":true });
>4.指定分片的数据库
db.runCommand({enablesharding:"baizhi"});
>5.设置库的片键信息
db.runCommand({shardcollection:"baizhi.users",key:{ _id:1}})
db.runCommand({shardcollection:"baizhi.emps",key:{ _id:"hashed"}})
# 总结
# 1.第一次搭建需要进入use admin 中操作进行初始化操作
# 2.重新启动集群只需要按照步骤以此启动 configserver routes 分片
# 启动过程中可能会报错但等全部启动之后就正常了
# 3.idea去连接集群时,只需要连接route服务端口就k
10.2老师搭建过程
这里是搭建了三个分片
4.指定分片的数据库
db.runCommand({enablesharding:“baizhi”});
5.设置库的片键信息
db.runCommand({shardcollection:“baizhi.users”,key:{ _id:1}})
db.runCommand({shardcollection:“baizhi.emps”,key:{ _id:“hashed”}})
总结
1.第一次搭建需要进入use admin 中操作进行初始化操作
2.重新启动集群只需要按照步骤以此启动 configserver routes 分片
启动过程中可能会报错但等全部启动之后就正常了
3.idea去连接集群时,只需要连接route服务端口就k