MongoDB - 入门篇
目录
- MongoDB - 入门篇
- 1 MongoDB介绍
- 1.1 特点
- 1.2 适用场景
- 1.3 相关概念
- 2 安装MongoDB
- 2.1 Liunx下安装mongoDB
- 2.2 Docker安装mongoDB
- 3 Mongodb支持的数据类型
- 3.1 null
- 3.2 布尔类型
- 3.3 数值类型
- 3.4 字符串
- 3.5 日期类型
- 3.6 正则表达式
- 3.7 数组
- 3.8 内嵌文档
- 3.9 _id和ObjectId
- 3.10 代码
- 3.11 二进制数据
- 4 MongoDB常用指令
- 5 Java 使用 MongoDB
- 6 MongDB索引
- 6.1 创建索引的语法
- 6.2 索引分类
- 7 MongoDB备份与恢复
- 7.1 mongodump命令来备份数据
- 7.2 MongoDB数据恢复
1 MongoDB介绍
MongoDB是一个基于分布式文件存储的数据库,旨在为WEB应用提供可扩展的高性能数据存储解决方案。
MongoDB支持的数据结构非常松散,是类似Json的 bson 格式,因此可以存储比较复杂的数据类型。Mongo最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。
说明:BSON是一种计算机数据交换格式,主要被用作MongoDB数据库中的数据存储和网络传输格式。它是一种二进制表示形式,能用来表示简单数据结构、关联数组(MongoDB中称为“对象”或“文档”)以及MongoDB中的各种数据类型。BSON之名缘于JSON,含义为Binary JSON(二进制JSON)。
1.1 特点
- 面向集合存储,易存储对象类型的数据
- 支持动态查询
- 支持完全索引,包含内部对象
- 支持复制和故障恢复
- 支持多种开发语言
- 使用高效的二进制数据存储,包括大型对象(如视频等)
1.2 适用场景
- 网站实时数据处理。它非常适合实时的插入、更新与查询,并具备网站实时数据存储所需的复制及高度伸缩性。
- 缓存。由于性能很高,它适合作为信息基础设施的缓存层。在系统重启之后,由它搭建的持久化缓存层可以避免下层的数据源过载。
- 高伸缩性的场景。非常适合由数十或数百台服务器组成的数据库,它的路线图中已经包含对MapReduce引擎的内置支持。
1.3 相关概念
2 安装MongoDB
2.1 Liunx下安装mongoDB
第一步:下载安装包
- 下载地址:https://www.mongodb.com/download-center#community
第二步:上传到Linux,并解压
$ tar -zxvf mongodb-linux-x86_64-4.0.19-rc0.tgz
第三步:移动文件到自定义目录
$ mv mongodb-linux-x86_64-4.0.19-rc0
/home/admin/myapps/mongodb
$ cd /home/admin/myapps/mongodb/
$ ll
total 200
drwxr-xr-x. 2 root root 4096 Jun 3 00:10 bin
-rw-r--r--. 1 root root 30608 Jun 2 15:01 LICENSE-Community.txt
-rw-r--r--. 1 root root 16726 Jun 2 15:01 MPL-2
-rw-r--r--. 1 root root 2601 Jun 2 15:01 README
-rw-r--r--. 1 root root 60005 Jun 2 15:01 THIRD-PARTY-NOTICES
-rw-r--r--. 1 root root 81355 Jun 2 15:02 THIRD-PARTY-NOTICES.gotools
第四步:系统profile配置
$ vi /etc/profile
编辑代码:
export mongodb_home=/home/admin/myapps/mongodb # mongodb的安装目录
export PATH=$PATH:$mongodb_home/bin
保存后,重启系统配置
$ source /etc/profile
第五步:创建数据库目录
$ pwd
/home/admin/myapps
$ mkdir mongodbdata # 存放数据库的目录
第六步:创建日志文件和配置文件
$ mkdir logs
$ cd logs
$ touch mongodb.log
$ cd ..
$ cd mongodb
$ cd bin
$ vi mongodb.conf # 配置文件存放在bin目录下
- mongodb.conf配置内容:
dbpath = /home/admin/myapps/mongodbdata # 数据文件存放目录
logpath = /home/admin/myapps/logs/mongodb.log # 日志文件存放目录
port = 27017 # 端口
fork = true # 以守护程序的方式启用,即在后台运行
第七步:启动mongodb服务端
$ ./mongod -f mongodb.conf
about to fork child process, waiting until server is ready for connections.
forked process: 2962
child process started successfully, parent exiting
第八步:运行客户端
$ ./mongo
2.2 Docker安装mongoDB
1、查看可用的 MongoDB 版本
我们可以用 docker search mongo 命令来查看可用版本:
- 获取最新版的MongoDB镜像
$ docker pull mongo:latest
等待下载完成…
- 查看本地镜像
$ docker images
- 容器运行
安装完成后,我们可以使用以下命令来运行 mongo 容器:
$ docker run -itd --name mongo -p 27017:27017 mongo --auth
参数说明:
- -p 27017:27017 :映射容器服务的 27017 端口到宿主机的 27017 端口。外部可以直接通过宿主机 ip:27017 访问到 mongo 的服务。
- –auth:需要密码才能访问容器服务。
- 安装成功
我们可以通过 docker ps 命令查看容器的运行信息:
接着使用以下命令添加用户和设置密码,并且尝试连接。
$ docker exec -it mongo mongo admin
# 创建一个名为 admin,密码为 123456 的用户。
> db.createUser({ user:'admin',pwd:'123456',roles:[ { role:'userAdminAnyDatabase', db: 'admin'},"readWriteAnyDatabase"]});
# 尝试使用上面创建的用户信息进行连接。
> db.auth('admin', '123456')
3 Mongodb支持的数据类型
3.1 null
null 用于表示空值或不存在的字段。示例如下:
{"x" : null}
3.2 布尔类型
布尔型数据有true和false两个值。示例如下:
{"x" : true}
3.3 数值类型
在Mongo shell中,默认使用 64 位浮点型数据。因此,会有以下两种数值形式:
{"x" : 2.32}//或{"x" : 2}
对于整数类型,可以使用NumberInt()
(位有符号整型)或NumberLong()
(8位有符号整型)方法进行转换。示例如下:
{"x" : NumberInt(2)}
{"x" : NumberLong(2)}
3.4 字符串
MongoDB中字符串类型使用UTF-8编码的字符表示。示例如下:
{"x" : "123@qq.com"}
3.5 日期类型
MongoDB中日期使用时间戳表示,单位为毫秒,不存储时区。示例如下:
{"x" : new Date()}
创建日期对象时应该使用new Date(),而非构造函数Date()。将构造函数作为函数时返回的日期格式是字符串,而非日期对象(与JavaScript工作机制有关)。
3.6 正则表达式
MongoDB中可使用与JavaScript相同的正则表达式进行查询筛选等。示例如下:
{"x" : /murphy/i}
3.7 数组
数据集可以用数组格式存储,与JavaSript中的数组表示相同。示例如下:
{"x" : ["murphy", "murphy.com"]}
数组中可以包含不同类型的数据元素,包括内嵌文档和数组等。所有MongoDB中键-值对支持的数据类型都可以用做数组的值。
3.8 内嵌文档
文档中可以嵌套一个子文档。在MongoDB文档总大小限制为16MB,建议使用子文档的形式组织数据,子文档查询效率要高于多键查询。示例如下:
{"x" : {"murphy" : "murphy.com"}}
文档可以做为键的值,即:内嵌文档。MongoDB与关系型数据库相比,最大的优势就是内嵌文档。与关系型数据库的扁平化数据结构相比,使用内嵌文档可以数据的组织方式更加自然。
3.9 _id和ObjectId
MongoDB中每个文档都有一个"_id
" 键, " id"可以是任何类型,不指"_id"时MongoDB会生成一个ObjectId对象。示例如下:
{"_id" : ObjectId()}
ObjectId是一个 12 字节( 24 个十六进制数字)的存储空间,ObjectId的 12 字节数据组织方式如下:
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11
时间戳 | 机器码 | PID | 计数器
对于如下一个ObjectId,其各位字符含义为:
{"_id" : ObjectId("5444cce6aef53b0f343e2b9b")}
/* 上面ObjectId各位字符含义如下 */
// 5444cce6,第0〜3字节(第1〜8位)为时间戳
// aef53b,第4〜6字节(第9〜14位)为机器码
// 0f34,第7〜8字节(第15〜18位)为进程ID
// 3e2b9b,第9〜11字节(第19〜24位)为自增计数器
3.10 代码
MongoDB的文档和代码中可以包括JavaScript代码。示例如下:
{"x" : function(){ /*这里是一段JavaScript代码*/}}
3.11 二进制数据
二进制数据是一个二进制字节的字作串,要保存非UTF-8字符到数据库中,只能使用十进制数据。
4 MongoDB常用指令
登录:
> mongo ip地址 // 默认端口号27017
注意:如果没有指定bind_ip
,会导致 mongodb 默认绑定为127.0.0.1,导致外部无法访问
修改mongodb.conf文件:
bind_ip=0.0.0.0
退出:
查看数据库(数据库中至少有一条数据,此时的数据库才会显示出来):
> show dbs
切换数据库:
> use 数据库名 // 这个指令也可以直接创建数据库,但只有添加数据后,show dbs才能看到该数据库
查看当前数据库,默认数据库:test
> db
查看所有的数据集
> show collections
删除当前数据库
> db.dropDatabase()
创建集合(相当于创建表)
> db.createCollection("user1")
删除集合
> db.collectionName.drop()
集合重命名
> db.oldCollectionName.renameCollection("newName")
新增数据
> db.collectionName.insert({"key":value,"key":value})
或
> db.collectionName.save({"key":value,"key":value})
查询所有数据
> db.collectionName.find()
条件查询-find()
以非结构化的方式展示文档
> db.collectionName.find({"age":26}) //查询等值关系
> db.collectionName.find({age : {$gt : 100}}) // 大于100
> db.collectionName.find({age : {$gte : 100}}) //大于等于100
> db.collectionName.find({age : {$lt : 150}}) //小于150
> db.collectionName.find({age : {$lte : 150}}) //小于等于150
> db.collectionName.find({age : {$lt :200, $gt : 100}}) //大于100,小于200
如果你需要以易读的方式来读取数据,可以使用pretty()
方法,语法格式如下
> db.collectionName.find().pretty()
and 关系
MongoDB 的 find() 方法可以传入多个键(key),每个键(key)以逗号隔开,即常规 SQL 的 AND 条件
语法:> db.collectionName.find({key1:value1, key2:value2}).pretty()
示例:> db.collectionName.find({"by":"java", "title":"MongoDB学习"}).pretty()
or 关系
MongoDB OR 条件语句使用了关键字 $or
语法:> db.collectionName.find({$or:[{key1: value1}, {key2:value2}]}).pretty()
示例:> db.collectionName.find({$or:[{"by":"java"},{"title": "MongoDB学习"}]}).pretty()
清空集合数据
> db.collectionName.remove({}) // 条件删除:remove({key:value})
// 删除满足条件的一条数据:remove({key:value},1)
查询一条数据
> db.collectionName.findOne();
查询指定列
> db.collectionName.find({},{name:1,age:1,sex_orientation:true})
查询指定字段的数据,并去重
> db.collectionName.distinct('sex')
对结果集排序
> db.collectionName.find().sort({salary:1}) // 升序
> db.collectionName.find().sort({salary:-1}) // 降序
统计记录数
> db.collectionName.find().count()
查询限定条数
> db.collectionName.find().limit(number)
使用limit()
方法来读取指定数量的数据外,还可以使用skip()
方法来跳过指定数量的数据,skip方法同样接受一个数字参数作为跳过的记录条数。
> db.collectionName.find().limit(NUMBER).skip(NUMBER)
更新数据
db.collectionName.update(<query>,<update>,{upsert: <boolean>, multi: <boolean>)
参数说明:
query
:update的查询条件update
:update的对象和一些更新的操作符(如$,$inc
…)等,也可以理解为sql update查询内set后面的upsert
:可选,如果不存在update的记录,是否插入objNew;true为插入,默认是false,不插入。multi
:可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。
示例:> db.collectionName.update({name:'tom'},{$set:{age:23}},false,true)
5 Java 使用 MongoDB
第一步:添加 mongodb-java-driver 驱动包
<dependencies>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>3.2.2</version>
</dependency>
</dependencies>
第二步:连接数据库并操作数据 - Insert 操作
/**
* 测试连接MongoDB - 无密码连接
*
* @author murphy
*/
public class MongoTest {
public static void main(String[] args) {
// 1. 建立MongoDB的连接
MongoClient mongoClient = new MongoClient("192.168.2.130",27017);
// 2. 得到数据源
MongoDatabase mydb1 = mongoClient.getDatabase("mydb1");
// 得到数据库信息
System.out.println(mydb1);
// 3. 得到集合 - 创建新集合
// mydb1.createCollection("movies");
// 得到原有集合
MongoCollection<Document> user = mydb1.getCollection("user");
// 4. 集合的增删改查
// Insert
Document document = new Document("_id", 1101);
document.append("name","qianzai");
document.append("age",20);
user.insertOne(document);
System.out.println("Insert Successfully!");
}
}
/**
* 测试连接MongoDB - 密码模式
*
* @author murphy
*/
public class MongoTest {
public static void main(String[] args) {
// 连接到MongoDB服务,如果是远程连接需要替换为IP地址
// ServerAddress() - 参数1:服务器地址 | 参数2:端口
ServerAddress serverAddress = new ServerAddress("101.34.225.2",27017);
List<ServerAddress> address = new ArrayList<>();
address.add(serverAddress);
// MongoCredential.createScramSha1Credential() - 参数1:用户名 | 参数2:数据库名称 | 参数3:密码
MongoCredential credential = MongoCredential.createScramSha1Credential("murphy", "mydb1", "123123".toCharArray());
List<MongoCredential> credentials = new ArrayList<>();
credentials.add(credential);
// 通过连接认证获取MongoDB连接
MongoClient mongoClient = new MongoClient(address, credentials);
// 连接到数据库
MongoDatabase mydb1 = mongoClient.getDatabase("mydb1");
// 得到数据库信息
System.out.println(mydb1);
// 得到原有集合
MongoCollection<Document> user = mydb1.getCollection("user");
// 集合的增删改查
// Insert
Document document = new Document("_id", 1101);
document.append("name","qianzai");
document.append("age",20);
user.insertOne(document);
System.out.println("Insert Successfully!");
}
}
密码认证问题分析:https://blog.csdn.net/u013631121/article/details/81089971
测试查看
Query 操作
/**
* 测试连接MongoDB
*
* @author murphy
*/
public class MongoTest {
public static void main(String[] args) {
// 连接到MongoDB服务,如果是远程连接需要替换为IP地址
// ServerAddress() - 参数1:服务器地址 | 参数2:端口
ServerAddress serverAddress = new ServerAddress("192.168.2.130",27017);
List<ServerAddress> address = new ArrayList<>();
address.add(serverAddress);
// MongoCredential.createScramSha1Credential() - 参数1:用户名 | 参数2:数据库名称 | 参数3:密码
MongoCredential credential = MongoCredential.createScramSha1Credential("murphy", "mydb1", "123123".toCharArray());
List<MongoCredential> credentials = new ArrayList<>();
credentials.add(credential);
// 通过连接认证获取MongoDB连接
MongoClient mongoClient = new MongoClient(address, credentials);
// 连接到数据库
MongoDatabase mydb1 = mongoClient.getDatabase("mydb1");
// 得到数据库信息
System.out.println(mydb1);
// 得到原有集合
MongoCollection<Document> user = mydb1.getCollection("user");
// Query
FindIterable<Document> documents = user.find();
MongoCursor<Document> iterator = documents.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
// 输出
Document{{_id=6172783d276f2759edc7ab78, name=murphy, age=21.0}}
Document{{_id=61727858276f2759edc7ab79, name=hanhan, age=23.0}}
Document{{_id=61727860276f2759edc7ab7a, name=tina, age=26.0}}
Document{{_id=1101, name=qianzai, age=20}}
Document{{_id=1102, name=heart, age=30}}
Update / Delete 操作
/**
* 测试连接MongoDB
*
* @author murphy
*/
public class MongoTest {
public static void main(String[] args) {
// 连接到MongoDB服务,如果是远程连接需要替换为IP地址
// ServerAddress() - 参数1:服务器地址 | 参数2:端口
ServerAddress serverAddress = new ServerAddress("192.168.2.130",27017);
List<ServerAddress> address = new ArrayList<>();
address.add(serverAddress);
// MongoCredential.createScramSha1Credential() - 参数1:用户名 | 参数2:数据库名称 | 参数3:密码
MongoCredential credential = MongoCredential.createScramSha1Credential("murphy", "mydb1", "123123".toCharArray());
List<MongoCredential> credentials = new ArrayList<>();
credentials.add(credential);
// 通过连接认证获取MongoDB连接
MongoClient mongoClient = new MongoClient(address, credentials);
// 连接到数据库
MongoDatabase mydb1 = mongoClient.getDatabase("mydb1");
// 得到数据库信息
System.out.println(mydb1);
// 得到原有集合
MongoCollection<Document> user = mydb1.getCollection("user");
// Update - 将heart的年龄改成32 - 多重改:updateMany
user.updateOne(Filters.eq("name","heart"), new Document("$set", new Document("age",32)));
// Delete - 删除qianzai的信息
user.deleteOne(new Document("name","qianzai"));
// Query
FindIterable<Document> documents = user.find();
MongoCursor<Document> iterator = documents.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
// 输出 - 经过删除与更新
Document{{_id=6172783d276f2759edc7ab78, name=murphy, age=21.0}}
Document{{_id=61727858276f2759edc7ab79, name=hanhan, age=23.0}}
Document{{_id=61727860276f2759edc7ab7a, name=tina, age=26.0}}
Document{{_id=1102, name=heart, age=32}}
6 MongDB索引
索引通常能够极大的提高查询的效率,如果没有索引,MongoDB在读取数据时必须扫描集合中的每个文件并选取那些符合查询条件的记录。索引是特殊的数据结构,索引存储在一个易于遍历读取的数据集合中,索引是对数据库表中一列或多列的值进行排序的一种结构。
6.1 创建索引的语法
> db.collection.createIndex(keys, options)
options 取值的含义:
6.2 索引分类
(1)默认索引
MongoDB有个默认的“ _id
”的键,相当于 “ 主键 ” 的角色。集合创建后系统会自动创建一个索引在 “_id
”键上,它是默认索引,索引名叫“_id_
”,是无法被删除的。我们可以通过以下方式查看:
(2)单列索引
在单个键上创建的索引就是单列索引,例如我们要在Users集合上给title键创建一个单列索引,语法如下:( 1 表示正序,-1逆序)
> db.collectionName.createIndex({"title":1})
(3)组合索引
另外,我们还可以同时对多个键创建组合索引。如下代码创建了按照“UserId”正序,“UserName”逆序的组合索引:
> db.collectionName.createIndex({"userid":1, "username":-1})
(4)唯一索引
唯一索引限制了对当前键添加值时,不能添加重复的信息。值得注意的是,当文档不存在指定键时,会被认为键值是“null”,所以“null”也会被认为是重复的,所以一般被作为唯一索引的键,最好都要有键值对。
对“UserId”创建唯一索引(这时候最后一个参数为“true”):
> db.collectionName.CreateIndex({"UserId":1}, {unique: true});
(5)TTL索引
TTL指生命周期的意思。即存储的document存储带有过期时间属性,超过生命周期自己主动删除。像日志数据、系统自己主动产生的暂时数据、会话数据等均符合这一场景。构建方式如:
db.log_events.createIndex({"createdAt":1},{expireAfterSeconds:3600})
(6)删除索引
新手常陷入的误区是,认为集合被删除,索引就不存在了。关系型数据库中,表被删除了,索引也不会存在。在MongoDB中不存在删除集合的说法,就算集合数据清空,索引都是还在的,要移除索引还需要手工删除。
> db.collectionName.dropIndexes()
删除集合指定索引
> db.collectionName.dropIndex("索引名称")
说明:drop()
集合时,索引也会删除,remove()
集合时,索引仍然存在
示例代码:
> db.users.remove({})
WriteResult({"nRemoved":3})
> db.users.getIndexes()
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "mydb1.users"
}
]
> db.users.drop()
true
> db.users.getIndexes()
[]
7 MongoDB备份与恢复
7.1 mongodump命令来备份数据
该命令可以导出所有数据到指定目录中。
mongodump命令可以通过参数指定导出的数据量级转存的服务器。
语法:
> mongodump -h dbhost -d dbname -o dbdirectory
-
-h
:MongDB所在服务器地址,例如:127.0.0.1,当然也可以指定端口号:127.0.0.1:27017
-
-d
:需要备份的数据库实例,例如:test
-
-o
:备份的数据存放位置,例如:c:\data\dump,当然该目录需要提前建立,在备份完成后,系统自动在dump目录下建立一个test目录,这个目录里面存放该数据库实例的备份数据。
示例
- 在本地使用 27017 启动你的mongod服务。打开命令提示符窗口,进入MongoDB安装目录的bin目录输入命令
mongodump
:
> mongodump
# 文件存储位置 - dump
执行以上命令后,客户端会连接到ip为 127.0.0.1 端口号为 27017 的MongoDB服务上,并备份所有数据到 bin/dump/
目录中。命令输出结果如下:
[root@localhost bin]# mongodump
writing admin.system.version to
done dumping admin.system.version (1 document)
writing mydb1.users to
writing mydb1.student to
done dumping mydb1.users (4 documents)
done dumping mydb1.student (0 documents)
mongodump 命令可选参数列表如下所示:
7.2 MongoDB数据恢复
mongodb使用 mongorestore 命令来恢复备份的数据。
语法
> 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。 你不能同时指定 和 --dir 选项,–dir也可以设置备份目录。
-
--dir
:指定备份的目录 你不能同时指定 和 --dir 选项。
接下来我们执行以下命令:
> mongorestore
执行以上命令输出结果如下:
[root@localhost bin]# mongorestore
.....
no indexes to restore
finished restoring mydb1.users (4 documents)
done