目录
一.初识MongoDB
1.介绍
2.作用
二.MongoDB的概念
1、数据库的概念
1.1、作用:
1.2、分类:(根据SQL语言的支持)
2、MongoDB基础概念
四、MongoDB的使用
1、连接MongoDB
1.1、DOS命令连接
1.2、点击安装目录下的mongo.exe-》E:\MongoDB\Server\4.0\bin\mongo.exe
2、基础语法
2.1、概念:
2.2、语法
3、功能与特性
3.1、索引
3.2、聚合(aggregate)
3.3、复制(副本集)
3.4、分片
3.5、备份(mongodump)与恢复(mongorestore)
3.6、监控
4、java使用MongoDB
参考:https://www.imooc.com/video/5934(慕课网)
参考:http://www.runoob.com/mongodb/mongodb-intro.html(菜鸟教程)
学习网站:
就是数据的仓库,不同的数据库存放数据的组织不同,且提供了不同种类的查询。
SQL数据库:支持SQL语言的数据库。(由于表的定义,横向扩展不够灵活。即时存取、事物操作等有时也没必要使用)
NoSql数据库:不支持SQL语言的数据库。(没有多表连合查询)
SQL术语/概念 | MongoDB术语/概念 | 解释/说明 |
---|---|---|
database | database | 数据库 |
table | collection | 数据库表/集合 |
row | document | 数据记录行/文档 |
column | field | 数据字段/域 |
index | index | 索引 |
table joins | 表连接,MongoDB不支持 | |
primary key | primary key | 主键,MongoDB自动将_id字段设置为主键 |
MongoDB
Mongo
索引
集合
赋值集
分片
数据均衡
三、部署数据库服务
搭建简单的单击服务
搭建具有冗余容错功能的复制集
搭建大规模数据集群(拥有分片处理)
完成集群的自动部署
语法(菜鸟教程):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的服务器。(不启动服务器也可运行,但是只能用于测试)
MongoDB默认数据库为test。
文档的数据结构为BSON(和JSON基本一样,是JSON的二进制形式存储格式(Binary JSON))
创建数据库:use DATABASE_NAME (如果数据库不存在,则创建。否则切换到指定数据库。)
查看所有数据库:show dbs (刚创建的数据库如果没有插入数据,则无法通过show dbs显示)
删除数据库:db.dropDatabase()
删除集合:db.collection.drop()(collection为集合名字)
创建集合:db.createCollection(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(
替换已有的文档:db.collection.save(
删除文档:db.conllection.remove(
查询文档:db.col.find(query,projection) (col为集合名,在加上“.pretty()”则可使查询出的内容工整)
//全为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模式 指定不返回的键,返回其他键
操作 | 格式 | 范例 | RDBMS中的类似语句 |
---|---|---|---|
等于 | { } |
db.col.find({"by":"菜鸟教程"}).pretty() |
where by = '菜鸟教程' |
小于 | { |
db.col.find({"likes":{$lt:50}}).pretty() |
where likes < 50 |
小于或等于 | { |
db.col.find({"likes":{$lte:50}}).pretty() |
where likes <= 50 |
大于 | { |
db.col.find({"likes":{$gt:50}}).pretty() |
where likes > 50 |
大于或等于 | { |
db.col.find({"likes":{$gte:50}}).pretty() |
where likes >= 50 |
不等于 | { |
db.col.find({"likes":{$ne:50}}).pretty() |
where likes != 50 |
基于BSON,检索匹配的数据类型(特殊) |
{ |
|
类型 | 数字 | 备注 |
---|---|---|
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用于降序)
创建索引:db.collection.createIndex(key,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. |
主要用于处理数据(诸如统计平均值,求和等),并返回计算后的数据结果。优点类似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"}}}]) |
管道操作符:
3.3.1、原理
至少需要2个节点,主节点(为单个,负责处理数据端请求)、从节点(可为多,负责复制主节点上的数据)。其中主节点不是固定的一个,任何节点都可以为主节点。(因为主节点宕机后,从节点会成为主节点)
3.3.2 、特征
3.3.3、使用
3.4.1、作用:
3.4.2、分片集群结构主要组件
备份:mongodump -h dbhost -d dbname -o dbdirectory
语法 | 描述 | 实例 |
---|---|---|
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
在你已经安装部署并允许MongoDB服务后,你必须要了解MongoDB的运行情况,并查看MongoDB的性能。这样在大流量得情况下可以很好的应对并保证MongoDB正常运作。
MongoDB中提供了mongostat 和 mongotop 两个命令来监控MongoDB的运行情况。
3.6.1、mongostat命令
mongodb自带的状态监测工具,在命令行下使用。它会间隔固定时间获取mongodb的当前运行状态,并输出。
如果你发现数据库突然变慢或者有其他问题的话,你第一手的操作就考虑采用mongostat来查看mongo的状态。
使用:启动你的Mongod服务,进入到你安装的MongoDB目录下的bin目录, 然后输入mongostat命令
3.6.2、mongotop命令
也是一个内置工具,提供了一个方法,用来跟踪一个MongoDB实例,查看哪些大量的时间花费在读取和写入数据。
mongotop提供每个集合的水平的统计数据。默认情况下,mongotop返回值的每一秒。
使用:输入mongotop命令
MongoDB3.0以上在连接时需要三个jar包:参考:https://blog.csdn.net/hotdust/article/details/51315197
org.mongodb
mongo-java-driver
3.0.4
org.mongodb
mongodb-driver
3.0.4
org.mongodb
mongodb-driver-core
3.0.4
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 addrs = new ArrayList();
// addrs.add(serverAddress);
//
// //MongoCredential.createScramSha1Credential()三个参数分别为 用户名 数据库名称 密码
// MongoCredential credential = MongoCredential.createScramSha1Credential("username", "databaseName", "password".toCharArray());
// List credentials = new ArrayList();
// 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 collection = mgDatabase.getCollection("test");
System.out.println("集合test选择成功");
}
//3.插入文档
@Test
public void insertDocument(){
MongoCollection collection = mgDatabase.getCollection("test");
System.out.println("集合test选择成功");
//插入文档
/**
* 1. 创建文档 org.bson.Document 参数为key-value的格式
* 2. 创建文档集合List
* 3. 将文档集合插入数据库集合中 collection.insertMany(List) 插入单个文档可以用 collection.insertOne(Document)
* */
Document document = new Document("title","MongoDB").
append("description", "database").
append("likes", 101).
append("by", "又是一条记录");
List documents = new ArrayList();
documents.add(document);
collection.insertMany(documents);
System.out.println("文档插入成功");
}
//4.检查所有文档
@Test
public void findDocument(){
MongoCollection collection = mgDatabase.getCollection("test");
System.out.println("集合test选择成功");
//检索所有文档
/**
* 1. 获取迭代器FindIterable
* 2. 获取游标MongoCursor
* 3. 通过游标遍历检索出的文档集合
* */
FindIterable findIterable = collection.find();
MongoCursor mgCursor = findIterable.iterator();
while(mgCursor.hasNext()){
System.out.println(mgCursor.next());
}
System.out.println("检查完成");
}
//5.更新文档
@Test
public void updateDocument(){
MongoCollection 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 collection = mgDatabase.getCollection("test");
System.out.println("集合test选择成功");
//删除符合条件的第一个文档
collection.deleteOne(Filters.eq("likes",200));
System.out.println("删除符合条件的第一个文档成功");
}
//6.1、删除符合条件的所有文档
@Test
public void deleteManyDocument(){
MongoCollection collection = mgDatabase.getCollection("test");
System.out.println("集合test选择成功");
//删除符合条件的所有文档(就是变了一个deleteMany方法)
collection.deleteMany(Filters.eq("likes",210));
System.out.println("删除符合条件的所有文档成功");
}
}
表示多个文档在逻辑上的相互联系。
文档间可以通过嵌入和引用来建立联系。
关系:
例:一个用户可以有多个地址(这个只是一个说明,不做实际应用)
//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"
}
//不用想复杂了,就是将地址以数组的形式保存在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()
引用式关系是设计数据库时经常用到的方法,这种方法把用户数据文档和用户地址数据文档分开,通过引用文档的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"]}})
DBRef的形式:{ $ref : , $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"
}
达成覆盖索引查询的条件:
原理:
例:
//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、处理多种常见故障(保证集群的正常运行)
单节点失效如何恢复工作
数据库意外被杀死,如何进行数据恢复
数据库发生拒绝服务时如何排查原因
数据库磁盘快满时如何处理