目录
1.2、点击安装目录下的mongo.exe-》E:\MongoDB\Server\4.0\bin\mongo.exe
3.5、备份(mongodump)与恢复(mongorestore)
参考:https://www.imooc.com/video/5934(慕课网)
参考:http://www.runoob.com/mongodb/mongodb-intro.html(菜鸟教程)
学习网站:
- www.mongoing.com(国内官网) docs.mongoing.com(中文文档)
- www.mongodb.org(官网)
- www.mongodb.com
- github.com/mongodb(源码)
一.初识MongoDB
1.介绍
- 基于分布式文件存储的数据库。开源的NoSQL数据
- 介于关系型数据库与非关系型数据库之间的产品(非关系型数据库中功能最全,最像关系型数据库的)。
- 数据格式为类似Json的Bson格式。面向集合存储。
- 支持的查询语言非常强大,语法类似于面向对象的查询语言,还支持对数据建立索引。
- 特点:高性能、易部署、易使用、存储数据非常方便。(每个软件、框架都这样说......)
2.作用
- 为WEB应用提供高性能数据存储解决方案
二.MongoDB的概念
1、数据库的概念
就是数据的仓库,不同的数据库存放数据的组织不同,且提供了不同种类的查询。
1.1、作用:
- 有组织的存放数据(只需根据数据库提供的接口写入)
- 按照不同的需求进行查询。
1.2、分类:(根据SQL语言的支持)
SQL数据库:支持SQL语言的数据库。(由于表的定义,横向扩展不够灵活。即时存取、事物操作等有时也没必要使用)
- Oracle
- MySql
NoSql数据库:不支持SQL语言的数据库。(没有多表连合查询)
- Redis:键值存取,支持部分事物
- MongoDB:本身不支持事物,没有表结构的概念
2、MongoDB基础概念
SQL术语/概念 | MongoDB术语/概念 | 解释/说明 |
---|---|---|
database | database | 数据库 |
table | collection | 数据库表/集合 |
row | document | 数据记录行/文档 |
column | field | 数据字段/域 |
index | index | 索引 |
table joins | 表连接,MongoDB不支持 | |
primary key | primary key | 主键,MongoDB自动将_id字段设置为主键 |
MongoDB
Mongo
索引
集合
赋值集
分片
数据均衡
三、部署数据库服务
搭建简单的单击服务
搭建具有冗余容错功能的复制集
搭建大规模数据集群(拥有分片处理)
完成集群的自动部署
四、MongoDB的使用
1、连接MongoDB
语法(菜鸟教程):mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]
tips:不过好像这样输入不能连接,直接输入mongo就可以连接了
---------以下为后期补上内容--------
查看mongodb是否启动:cmd中输入 net start MongoDB 。如果没有启动服务则会重新启动(net stop MongoDB 停止启动)
mongo:是运行mongo的数据库。
mongod:启动mongo的守护进程(mongo daemon),启动mongo的服务器。(不启动服务器也可运行,但是只能用于测试)
1.1、DOS命令连接
- 先建立环境变量“变量名:MONGODB_HOME,变量值:E:\MongoDB\Server\4.0”(如果不建立,则需通过cmd的cd命令到该目录下的bin去执行mongo.exe)
- 在path命令中新建:“%MONGODB_HOME%\bin”
- 然后可直接在cmd命令中输入“mongo”运行mongoDB服务(mongo好像也有的版本是mongodb)
1.2、点击安装目录下的mongo.exe-》E:\MongoDB\Server\4.0\bin\mongo.exe
2、基础语法
2.1、概念:
MongoDB默认数据库为test。
文档的数据结构为BSON(和JSON基本一样,是JSON的二进制形式存储格式(Binary JSON))
2.2、语法
创建数据库:use DATABASE_NAME (如果数据库不存在,则创建。否则切换到指定数据库。)
查看所有数据库:show dbs (刚创建的数据库如果没有插入数据,则无法通过show dbs显示)
删除数据库:db.dropDatabase()
删除集合:db.collection.drop()(collection为集合名字)
创建集合:db.createCollection(name,options) (当插入文档时会自动创建集合)
- name:要创建的集合名字
- options:可选,指定有关内存大小及索引的选项
capped | 布尔 | (可选)如果为 true,则创建固定集合。固定集合是指有着固定大小的集合,当达到最大值时,它会自动覆盖最早的文档。 当该值为 true 时,必须指定 size 参数。 |
autoIndexId | 布尔 | (可选)如为 true,自动在 _id 字段创建索引。默认为 false。 |
size | 数值 | (可选)为固定集合指定一个最大值(以字节计)。 如果 capped 为 true,也需要指定该字段。 |
max | 数值 | (可选)指定固定集合中包含文档的最大数量。 |
插入文档同时创建集合:db.mycol2.insert({"key":"value",......}) (mycol2为集合名)
查看已有集合:show collections
插入文档:db.COLLECTION_NAME.insert(document)
定义变量:document = ({key:'value',key2:'value2'}) (定义了变量就可以通过类似参数的形式进行文档插入(如上句语法))
更新文档:db.collection.update(<query>,<update>,{upsert:<boolean>,multi:<boolean>,writeConcern:<document>})
- 例:db.col.update({'title':'MongoDB 教程'},{$set:{'title':'MongoDB'}},{multi:true}) (更新查询到的数据的所有title)
- 更新操作符(参考地址):https://blog.youkuaiyun.com/u014344668/article/details/52460682
- query : update的查询条件,类似sql update查询内where后面的。
- update : update的对象和一些更新的操作符(如$,$inc...)等,也可以理解为sql update查询内set后面的
- upsert : 可选,这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入。
- multi : 可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。
- writeConcern :可选,抛出异常的级别。
替换已有的文档:db.collection.save(<document>,{writeConcern:<document>})
- document : 文档数据。
- writeConcern :可选,抛出异常的级别。
删除文档:db.conllection.remove(<query>,{justOne:<boolean>,writeConcern:<boolean>})
- 好的习惯:remove前先执行find()来判断执行条件是否正确
- 例:db.col.remove({'title':'MongoDB 教程'},true) (只删除第一条标题title为“MongoDB 教程”的数据)
- query :(可选)删除的文档的条件。
- justOne : (可选)如果设为 true 或 1,则只删除一个文档。
- writeConcern :(可选)抛出异常的级别。
查询文档:db.col.find(query,projection) (col为集合名,在加上“.pretty()”则可使查询出的内容工整)
- query :可选,使用查询操作符指定查询条件
- projection :可选,使用投影操作符指定返回的键。查询时返回文档中所有键值, 只需省略该参数即可(默认省略)。
//全为1(true)或为0(false),否则错误(除了inclusion模式id可指定为0) db.collection.find(query, {title: 1, by: 1}) // inclusion模式 指定返回的键,不返回其他键 db.collection.find(query, {title: 0, by: 0}) // exclusion模式 指定不返回的键,返回其他键
- 其他:findOne()方法,只返回一个文档
- MongoDB与RDBMS WHERE语句比较:
操作 格式 范例 RDBMS中的类似语句 等于 {<key>:<value>
}db.col.find({"by":"菜鸟教程"}).pretty()
where by = '菜鸟教程'
小于 {<key>:{$lt:<value>}}
db.col.find({"likes":{$lt:50}}).pretty()
where likes < 50
小于或等于 {<key>:{$lte:<value>}}
db.col.find({"likes":{$lte:50}}).pretty()
where likes <= 50
大于 {<key>:{$gt:<value>}}
db.col.find({"likes":{$gt:50}}).pretty()
where likes > 50
大于或等于 {<key>:{$gte:<value>}}
db.col.find({"likes":{$gte:50}}).pretty()
where likes >= 50
不等于 {<key>:{$ne:<value>}}
db.col.find({"likes":{$ne:50}}).pretty()
where likes != 50
- MongoDB AND条件:db.col.find({key1:value1, key2:value2}).pretty()
- MongoDB OR条件($or):db.col.find({$or:[{key1: value1}, {key2:value2}]}) (注意与AND条件语法有点不同,因为需要让AND与OR可以联合使用)
- AND和OR联合使用:db.col.find({"likes": {$gt:50}, $or: [{"by": "菜鸟教程"},{"title": "MongoDB 教程"}]}).pretty()
- 还有一个条件操作符:$type
基于BSON,检索匹配的数据类型(特殊)
{<key>:{$type:<value>}}
db.col.find({"title" : {$type : 2}}) 或: db.col.find({"title" : {$type : 'string'}})
类型 数字 备注 Double 1 String 2 Object 3 Array 4 Binary data 5 Undefined 6 已废弃。 Object id 7 Boolean 8 Date 9 Null 10 Regular Expression 11 JavaScript 13 Symbol 14 JavaScript (with scope) 15 32-bit integer 16 Timestamp 17 64-bit integer 18 Min key 255 Query with -1. Max key 127
读取指定数量记录:db.COLLECTION_NAME.find().limit(NUMBER)
跳过指定数量记录:db.COLLECTION_NAME.find().limit(NUMBER).skip(NUMBER) (先跳过,再读取指定数量)
排序:db.COLLECTION_NAME.find().sort({KEY:1})(sort({key:value})。value:1为升序、-1用于降序)
3、功能与特性
3.1、索引
- 能过极大的提高查询效率。(如果没有索引,MongoDB在读取数据时必须扫描集合中的每个文件,并选取那些符合查询条件的几率)
- 索引是特殊的数据结构,索引存储在一个易于遍历读取的数据集合中。(存储了字段的值,而值又指向记录。空间换时间)
- 索引是对数据库表中一列或多列的值进行排序的一种结构。
创建索引:db.collection.createIndex(key,options)
- 例1:db.col.createIndex({"title":1}) (为字段title升序创建索引)
- 例2:db.col.createIndex({'title':1,'description':-1}) (使用多个字段创建索引,关系型数据库也称作符合索引)
- 例3:db.col.createIndex({open:1,close:1},{background:true}) (后台创建索引)
- key:要创建索引的字段,1为升序建索引,-1为降序。
- options:
Parameter Type Description background Boolean 建索引过程会阻塞其它数据库操作,background可指定以后台方式创建索引,即增加 "background" 可选参数。 "background" 默认值为false。 unique Boolean 建立的索引是否唯一。指定为true创建唯一索引。默认值为false. name string 索引的名称。如果未指定,MongoDB的通过连接索引的字段名和排序顺序生成一个索引名称。 dropDups Boolean 在建立唯一索引时是否删除重复记录,指定 true 创建唯一索引。默认值为 false. sparse Boolean 对文档中不存在的字段数据不启用索引;这个参数需要特别注意,如果设置为true的话,在索引字段中不会查询出不包含对应字段的文档.。默认值为 false. expireAfterSeconds integer 指定一个以秒为单位的数值,完成 TTL设定,设定集合的生存时间。 v index version 索引的版本号。默认的索引版本取决于mongod创建索引时运行的版本。 weights document 索引权重值,数值在 1 到 99,999 之间,表示该索引相对于其他索引字段的得分权重。 default_language string 对于文本索引,该参数决定了停用词及词干和词器的规则的列表。 默认为英语 language_override string 对于文本索引,该参数指定了包含在文档中的字段名,语言覆盖默认的language,默认值为 language.
3.2、聚合(aggregate)
主要用于处理数据(诸如统计平均值,求和等),并返回计算后的数据结果。优点类似sql语句中的count(*)
语法:db.COLLECTION_NAME.aggregate(AGGREGATE_OPERATION)
例:db.mycol.aggregate([{$group : {_id:'$by_user',num_tutorial : {$sum : 1}}}])
类似于:select by_user,count(1) from mycol group by by_user
聚合表达式:
表达式 | 描述 | 实例 |
---|---|---|
$sum | 计算总和。 | db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : "$likes"}}}]) |
$avg | 计算平均值 | db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$avg : "$likes"}}}]) |
$min | 获取集合中所有文档对应值得最小值。 | db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$min : "$likes"}}}]) |
$max | 获取集合中所有文档对应值得最大值。 | db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$max : "$likes"}}}]) |
$push | 在结果文档中插入值到一个数组中。 | db.mycol.aggregate([{$group : {_id : "$by_user", url : {$push: "$url"}}}]) |
$addToSet | 在结果文档中插入值到一个数组中,但不创建副本。 | db.mycol.aggregate([{$group : {_id : "$by_user", url : {$addToSet : "$url"}}}]) |
$first | 根据资源文档的排序获取第一个文档数据。 | db.mycol.aggregate([{$group : {_id : "$by_user", first_url : {$first : "$url"}}}]) |
$last | 根据资源文档的排序获取最后一个文档数据 | db.mycol.aggregate([{$group : {_id : "$by_user", last_url : {$last : "$url"}}}]) |
管道操作符:
- $project:修改输入文档的结构。可以用来重命名、增加或删除域,也可以用于创建计算结果以及嵌套文档。
- $match:用于过滤数据,只输出符合条件的文档。$match使用MongoDB的标准查询操作。
- $limit:用来限制MongoDB聚合管道返回的文档数。
- $skip:在聚合管道中跳过指定数量的文档,并返回余下的文档。
- $unwind:将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值。
- $group:将集合中的文档分组,可用于统计结果。
- $sort:将输入文档排序后输出。
- $geoNear:输出接近某一地理位置的有序文档。
3.3、复制(副本集)
- 是将数据同步在多个服务器的过程。(分布式读取数据)
- 提供了数据的冗余备份,并在多个服务器上存储数据副本。(提高数据可用性、保证数据安全性)
- 允许从硬件故障、服务中断中恢复数据
3.3.1、原理
至少需要2个节点,主节点(为单个,负责处理数据端请求)、从节点(可为多,负责复制主节点上的数据)。其中主节点不是固定的一个,任何节点都可以为主节点。(因为主节点宕机后,从节点会成为主节点)
3.3.2 、特征
- N 个节点的集群
- 任何节点可作为主节点
- 所有写入操作都在主节点上
- 自动故障转移
- 自动恢复
3.3.3、使用
- 如果MongoDB服务在运行,先停止:net stop mongodb
- 通过 --replSet启动MongoDB:mongod --port 12345 --dbpath "E:\MongoDB\Server\4.0\data1" --replSet rs0
- 名为rs0,端口号为123456
- 新开一个cmd输入:mongo (显示则会与之前的不同,为: rs0:PRIMARY>“在这儿输入命令”)
- rs.initiate()启动一个新的副本集、rs.conf()查看副本集配置、rs.status()查看副本集状态
- 添加副本集成员(需要多台服务器启动mongo服务):rs.add(HOST_NAME:PORT)
- 例:rs.add("mongod1.net:27017")
- 只能通过主节点将Mongo(PRIMARY)服务添加到副本集中。判断是否为主节点:db.isMaster()
- 副本集与常见的主从不同,主从再主机宕机后所有服务将停止、副本集再主机宕机后副本会接管主节点。
3.4、分片
- 另一种集群,可以满足MongoDB数据量大量增长的需求。
- 当数据量过大,一太机器不足以存储数据、不足以提供可接受的读写吞吐量。则可通过多台机器上分割数据,是的数据库系统能存储和处理更多的数据
- 目前只做了解
3.4.1、作用:
- 复制所有的写入操作到主节点
- 延迟的铭感数据会在主节点查询
- 单个副本集限制在12个节点
- 当请求量巨大时会出现内存不足(使用分别来分割数据)
- 本地磁盘不足
- 垂直扩展价格昂贵
3.4.2、分片集群结构主要组件
- shard:用于储存实际的数据块,实际生产环境中一个shard server角色可有几台机器组一个replica set承担,防止主机单点故障
- Config Server:mongod实例,存储了整个ClusterMetadata,其中包括chunk信息
- Query Routers:前端路由,客户端由此接入,且让整个集群看上去像单一数据库,前端应用可以透明使用。
3.5、备份(mongodump)与恢复(mongorestore)
备份:mongodump -h dbhost -d dbname -o dbdirectory
- -h:MongoDB所在服务器地址。如:127.0.0.1或127.0.0.1:27017
- -d:需要备份的数据库实例。如:test
- -o:备份的数据存放位置。如:c:\data\dump (目录需提前建立)
- 例:C:\Windows\system32>mongodump -h 127.0.0.1 -d test -o C:\data (不需要(不能)再mongo下执行,打开cmd直接执行就好)
- mongodump命令可选参数
语法 描述 实例 mongodump --host HOST_NAME --port PORT_NUMBER 该命令将备份所有MongoDB数据 mongodump --host runoob.com --port 27017 mongodump --dbpath DB_PATH --out BACKUP_DIRECTORY mongodump --dbpath /data/db/ --out /data/backup/ mongodump --collection COLLECTION --db DB_NAME 该命令将备份指定数据库的集合。 mongodump --collection mycol --db test
恢复:mongorestore -h <hostname><:port> -d dbname <path>
- --host <:port>, -h <:port>:MongoDB所在服务器地址,默认为: localhost:27017
- --db , -d :需要恢复的数据库实例,例如:test,当然这个名称也可以和备份时候的不一样,比如test2
- --drop:恢复的时候,先删除当前数据,然后恢复备份的数据。就是说,恢复后,备份后添加修改的数据都会被删除,慎用哦!
- <path>:mongorestore 最后的一个参数,设置备份数据所在位置,例如:c:\data\dump\test。你不能同时指定 <path> 和 --dir 选项,--dir也可以设置备份目录。
- --dir:指定备份的目录,你不能同时指定 <path> 和 --dir 选项。
- 例:mongorestore -h 127.0.0.1 -d test --drop C:\data\test
3.6、监控
在你已经安装部署并允许MongoDB服务后,你必须要了解MongoDB的运行情况,并查看MongoDB的性能。这样在大流量得情况下可以很好的应对并保证MongoDB正常运作。
MongoDB中提供了mongostat 和 mongotop 两个命令来监控MongoDB的运行情况。
3.6.1、mongostat命令
mongodb自带的状态监测工具,在命令行下使用。它会间隔固定时间获取mongodb的当前运行状态,并输出。
如果你发现数据库突然变慢或者有其他问题的话,你第一手的操作就考虑采用mongostat来查看mongo的状态。
使用:启动你的Mongod服务,进入到你安装的MongoDB目录下的bin目录, 然后输入mongostat命令
- 例:E:\MongoDB\Server\4.0\bin>mongostat (如果配置了环境变量则无需进入该目录,直接输入mongostat即可)
3.6.2、mongotop命令
也是一个内置工具,提供了一个方法,用来跟踪一个MongoDB实例,查看哪些大量的时间花费在读取和写入数据。
mongotop提供每个集合的水平的统计数据。默认情况下,mongotop返回值的每一秒。
使用:输入mongotop命令
- 例:C:\Users\Administrator>mongotop (配置了环境变量,可直接输入mongotop)
- 例2:E:\mongodb-win32-x86_64-2.2.1\bin>mongotop 10
- 后面的10是<sleeptime>参数 ,可以不使用,等待的时间长度,以秒为单位,mongotop等待调用之间。通过的默认mongotop返回数据的每一秒。
- 例3:E:\mongodb-win32-x86_64-2.2.1\bin>mongotop --locks
- 报告每个数据库锁的使用情况(下面为输出结果字段说明)
- ns:包含数据库命名空间,后者结合了数据库名称和集合。
- db:包含数据库的名称。名为 . 的数据库针对全局锁定,而非特定数据库。
- total:mongod花费的时间工作在这个命名空间提供总额。
- read:提供了大量的时间,这mongod花费在执行读操作,在此命名空间。
- write:提供这个命名空间进行写操作,这mongod花了大量的时间。
4、java使用MongoDB
MongoDB3.0以上在连接时需要三个jar包:参考:https://blog.youkuaiyun.com/hotdust/article/details/51315197
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>3.0.4</version>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver</artifactId>
<version>3.0.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mongodb/mongodb-driver-core -->
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-core</artifactId>
<version>3.0.4</version>
</dependency>
MongDB在IDEA上使用实例:(使用了JUnit测试工具)
import com.mongodb.MongoClient;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.Filters;
import org.bson.Document;
import org.junit.Before;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
public class MongoDBJDBC {
//连接到数据库
MongoDatabase mgDatabase;
//测试时会自动在测试前运行的方法:获取MongoDB的连接
@Before
public void getmgDatabase(){
try{
//连接到mongodb服务
MongoClient mgClient = new MongoClient("localhost",27017);
//连接到数据库
mgDatabase = mgClient.getDatabase("test");
System.out.println("连接成功");
}catch(Exception e){
System.err.println( e.getClass().getName() + ": " + e.getMessage() );
}
}
//当连接数据库需要用户名、密码时使用
// @Before
// public void getmgDatabase(){
// try {
// //连接到MongoDB服务 如果是远程连接可以替换“localhost”为服务器所在IP地址
// //ServerAddress()两个参数分别为 服务器地址 和 端口
// ServerAddress serverAddress = new ServerAddress("localhost",27017);
// List<ServerAddress> addrs = new ArrayList<ServerAddress>();
// addrs.add(serverAddress);
//
// //MongoCredential.createScramSha1Credential()三个参数分别为 用户名 数据库名称 密码
// MongoCredential credential = MongoCredential.createScramSha1Credential("username", "databaseName", "password".toCharArray());
// List<MongoCredential> credentials = new ArrayList<MongoCredential>();
// credentials.add(credential);
//
// //通过连接认证获取MongoDB连接
// MongoClient mongoClient = new MongoClient(addrs,credentials);
//
// //连接到数据库
// mgDatabase = mongoClient.getDatabase("databaseName");
// System.out.println("数据库连接成功");
// } catch (Exception e) {
// System.err.println( e.getClass().getName() + ": " + e.getMessage() );
// }
// }
//1.创建集合
@Test
public void createConllection(){
mgDatabase.createCollection("test2");
System.out.println("集合创建成功");
}
//2.获取集合
@Test
public void getCollection(){
MongoCollection<Document> collection = mgDatabase.getCollection("test");
System.out.println("集合test选择成功");
}
//3.插入文档
@Test
public void insertDocument(){
MongoCollection<Document> collection = mgDatabase.getCollection("test");
System.out.println("集合test选择成功");
//插入文档
/**
* 1. 创建文档 org.bson.Document 参数为key-value的格式
* 2. 创建文档集合List<Document>
* 3. 将文档集合插入数据库集合中 collection.insertMany(List<Document>) 插入单个文档可以用 collection.insertOne(Document)
* */
Document document = new Document("title","MongoDB").
append("description", "database").
append("likes", 101).
append("by", "又是一条记录");
List<Document> documents = new ArrayList<Document>();
documents.add(document);
collection.insertMany(documents);
System.out.println("文档插入成功");
}
//4.检查所有文档
@Test
public void findDocument(){
MongoCollection<Document> collection = mgDatabase.getCollection("test");
System.out.println("集合test选择成功");
//检索所有文档
/**
* 1. 获取迭代器FindIterable<Document>
* 2. 获取游标MongoCursor<Document>
* 3. 通过游标遍历检索出的文档集合
* */
FindIterable<Document> findIterable = collection.find();
MongoCursor<Document> mgCursor = findIterable.iterator();
while(mgCursor.hasNext()){
System.out.println(mgCursor.next());
}
System.out.println("检查完成");
}
//5.更新文档
@Test
public void updateDocument(){
MongoCollection<Document> collection = mgDatabase.getCollection("test");
System.out.println("集合test选择成功");
//更新文档 将文档中likes=100的文档修改为likes=200
collection.updateMany(Filters.eq("likes",101),new Document("$set",new Document("likes",210)));
System.out.println("集合更新成功");
}
//6.1、删除第一个文档
@Test
public void deleteOneDocument(){
MongoCollection<Document> collection = mgDatabase.getCollection("test");
System.out.println("集合test选择成功");
//删除符合条件的第一个文档
collection.deleteOne(Filters.eq("likes",200));
System.out.println("删除符合条件的第一个文档成功");
}
//6.1、删除符合条件的所有文档
@Test
public void deleteManyDocument(){
MongoCollection<Document> collection = mgDatabase.getCollection("test");
System.out.println("集合test选择成功");
//删除符合条件的所有文档(就是变了一个deleteMany方法)
collection.deleteMany(Filters.eq("likes",210));
System.out.println("删除符合条件的所有文档成功");
}
}
五、MongoDB高级教程
1、MongoDB关系
表示多个文档在逻辑上的相互联系。
文档间可以通过嵌入和引用来建立联系。
关系:
- 1:1(1对1)
- 1:N(一对多)
- N:1(多对1)
- N:N(多对多)
例:一个用户可以有多个地址(这个只是一个说明,不做实际应用)
//user文档简单结构
{
"_id":ObjectId("52ffc33cd85242f436000001"),
"name": "Tom Hanks",
"contact": "987654321",
"dob": "01-01-1991"
}
//address文档简单结构
{
"_id":ObjectId("52ffc4a5d85242602e000000"),
"building": "22 A, Indiana Apt",
"pincode": 123456,
"city": "Los Angeles",
"state": "California"
}
1.1、嵌入式关系
- 使用嵌入式关系,我们可以把用户地址嵌入到用户的文档中。
- 不足:如果用户和用户地址在不断增加,数据量不断变大,会影响读写性能
//不用想复杂了,就是将地址以数组的形式保存在address中
"_id":ObjectId("52ffc33cd85242f436000001"),
"contact": "987654321",
"dob": "01-01-1991",
"name": "Tom Benzamin",
"address": [
{
"building": "22 A, Indiana Apt",
"pincode": 123456,
"city": "Los Angeles",
"state": "California"
},
{
"building": "170 A, Acropolis Apt",
"pincode": 456789,
"city": "Chicago",
"state": "Illinois"
}]
}
//可以使用这种方式来查询地址
>db.users.findOne({"name":"Tom Benzamin"},{"address"}:1)
//只显示满足条件的地址
db.test.find({"address":{$elemMatch:{"pincode":123456}}},{address:{$elemMatch:{"pincode":123456}}}).pretty()
1.2、引用式关系
引用式关系是设计数据库时经常用到的方法,这种方法把用户数据文档和用户地址数据文档分开,通过引用文档的id字段来建立关系。
//1、插入用户记录
> db.user.insert({
... "_id":ObjectId("52ffc33cd85242f436000001"),
... "contact": "987654321",
... "dob": "01-01-1991",
... "name": "Tom Benzamin",
... "address_ids": [
... ObjectId("52ffc4a5d85242602e000000"),
... ObjectId("52ffc4a5d85242602e000001")
... ]
... })
//2、插入城市记录
> db.address.insert({address:"长沙"})
WriteResult({ "nInserted" : 1 })
> db.address.insert({address:"北京"})
WriteResult({ "nInserted" : 1 })
> db.address.insert({address:"上海"})
WriteResult({ "nInserted" : 1 })
> db.address.insert({address:"广州"})
WriteResult({ "nInserted" : 1 })
> db.address.insert({address:"郴州"})
WriteResult({ "nInserted" : 1 })
//3、中间省略查询城市记录步骤(获取_id)
//4、修改用户的地址(address_ids)为查询出的地址"_id"
> db.user.update({contact:"987654321"},{$set:{address_ids:[ObjectId("5b7693f2ddc293f504101a07"), ObjectId("5b7693f8ddc293f504101a08")]}})
//5、获取用户的地址id
> var result = db.user.findOne({"name":"Tom Benzamin"},{"address_ids":1})
//6、获取相关联的地址(可直接输入变量名输出)
>var address = db.address.find({_id:{"$in":result["address_ids"]}})
2.数据库引用
- 在4.1中的引用式关系中,引用又分为两种:手动引用(Manual References)、DBRefs
- 理解:我们在不同的集合中 (address_home, address_office, address_mailing, 等)存储不同的地址(住址,办公室地址,邮件地址等)。这样,我们在调用不同地址时,也需要指定集合,一个文档从多个集合引用文档,我们应该使用 DBRefs。
DBRef的形式:{ $ref : , $id : , $db : }
- $ref:集合名称
- $id:引用的id
- $db:数据库名称,可选参数
- 实例:
//address DBRef 字段指定了引用的地址文档是在 runoob 数据库下的 address_home 集合,id 为 534009e4d852427820000002。 { "_id":ObjectId("53402597d852426020000002"), "address": { "$ref": "address_home", "$id": ObjectId("534009e4d852427820000002"), "$db": "runoob"}, "contact": "987654321", "dob": "01-01-1991", "name": "Tom Benzamin" } //我们通过指定 $ref 参数(address_home 集合)来查找集合中指定id的用户地址信息: >var user = db.users.findOne({"name":"Tom Benzamin"}) >var dbRef = user.address >db[dbRef.$ref].findOne({"_id":(dbRef.$id)}) //结果 { "_id" : ObjectId("534009e4d852427820000002"), "building" : "22 A, Indiana Apt", "pincode" : 123456, "city" : "Los Angeles", "state" : "California" }
3、覆盖索引查询
达成覆盖索引查询的条件:
- 所有的查询字段是索引的一部分(“一部分” 的理解就是:有可能这个字段是数组或文档,但是又与“不能达成”有冲突了)
- 所有的查询返回字段在同一个索引中
原理:
- 由于所有出现在查询中的字段是索引的一部分, MongoDB 无需在整个数据文档中检索匹配 查询条件和返回 使用相同索引的查询结果。
- 因为索引存在于RAM中,从索引中获取数据比通过扫描文档读取数据要快得多。
例:
//user集合
{
"_id": ObjectId("53402597d852426020000002"),
"contact": "987654321",
"dob": "01-01-1991",
"gender": "M",
"name": "Tom Benzamin",
"user_name": "tombenzamin"
}
//创建联合索引,字段为 gender 和 user_name :
>db.users.ensureIndex({gender:1,user_name:1})
//执行查询,该索引会覆盖这次查询(MongoDB的不会去数据库文件中查找。相反,它会从索引中提取数据,这是非常快速的数据查询。)
//由于我们的索引中不包括 _id 字段,_id在查询中会默认返回,我们可以在MongoDB的查询结果集中排除它。
>db.users.find({gender:"M"},{user_name:1,_id:0})
//执行查询(这种不会覆盖,因为他没有排除id)
>db.users.find({gender:"M"},{user_name:1})
以下的查询,不能使用覆盖索引查询:
- 所有索引字段是一个数组
- 所有索引字段是一个子文档
2.2
1、文档的读写更新删除
2、各种不同类型的索引的创建与使用
3、复杂的聚合查询
4、对数据集合进行分片,在不同分片中维持数据均衡
5、数据备份与恢复
6、数据迁移
五、运维
1、部署MongoDb集群
2、处理多种常见故障(保证集群的正常运行)
单节点失效如何恢复工作
数据库意外被杀死,如何进行数据恢复
数据库发生拒绝服务时如何排查原因
数据库磁盘快满时如何处理