mongoDB 学习

314 阅读10分钟

mongoDB 学习

一、mongoDB简介

  • MongoDB是一个开源、高性能、无模式的文档型数据库,是NoSQL数据库产品中的一种。是最像关系型数据库(MySQL)的非关系型数据库。
  • MongoDB支持的数据结构非常松散,是一种类似于 JSON 的格式叫 BSON,所以它既可以存储比较复杂的数据类型,又相当的灵活。
  • MongoDB中的记录是一个文档,它是一个由字段和值对(fifield:value)组成的数据结构。即一个文档认为就是一个对象。字段的数据类型是字符型,它的值除了使用基本的一些类型外,还可以包括其他文档、普通数组和文档数组。

二、mongoDB 特点

Mysql 和 MongoDb 的一些名词的对比:

MysqlMongoDB
数据库(Database)数据库(Database)
表(table)集合(collection)
行(row)文档(Document)
字段(column)域(field)
索引(index)索引(index)
表连接(table joins)不支持表连接,通过嵌入式文档来替代多表连接
主键(primary key)主键(primary key)

BOSN 的数据类型,此处盗用一张网上的图(侵权删) image.png

MongoDB的特点:

  • 高性能:

MongoDB提供高性能的数据持久性。特别是对嵌入式数据模型的支持减少了数据库系统上的I/O活动

  • 高可用性:

MongoDB的复制工具称为副本集(replica set),它可提供自动故障转移和数据冗余

  • 高扩展性:

MongoDB提供了水平可扩展性作为其核心功能的一部分。分别将数据分布在一组集群的机器上。

  • 丰富的查询支持:

MongoDB支持丰富的查询语言,支持读和写操作(CRUD),比如数据聚合、文本搜索和地理空间查询等。

  • 其他特点:如无模式(动态模式)、灵活的文档模型

**

三、安装启动MongoDB

这里演示如何在linux上安装启动MongoDB,并通过工具连接

安装环境和工具:

  • centos 7
  • finalshell
  • navicat 12.1

1,安装依赖

sudo yum install libcurl openssl

2,获取下载链接

www.mongodb.com/try/downloa… image.png

3,开始下载

wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-4.4.1.tgz

4,解压到指定目录

mkdir /usr/local/mongodb
tar -zxvf mongodb-linux-x86_64-4.0.10.tgz -C /usr/local/mongodb

5,新建数据存储目录,修改配置文件

cd /usr/local/mongodb/
# 数据存储目录
mkdir -p  data/db
# 日志存储目录
mkdir logs

新建并修改配置文件:

vim mongod.conf

配置文件可直接拷贝使用(这个文件的格式可以用在线YAML格式化一下,避免出现问题 www.bejson.com/validators/…

systemLog:
  #MongoDB发送所有日志输出的目标指定为文件
  # #The path of the log file to which mongod or mongos should send all diagnostic logging information
  destination: file
  #mongod或mongos应向其发送所有诊断日志记录信息的日志文件的路径
  path: "/usr/local/mongodb/logs/mongod.log"
  #当mongos或mongod实例重新启动时,mongos或mongod会将新条目附加到现有日志文件的末尾
  logAppend: true
storage:
  #mongod实例存储其数据的目录。storage.dbPath设置仅适用于mongod
  ##The directory where the mongod instance stores its data.Default Value is "/data/db"
  dbPath: "/usr/local/mongodb/data/db"
  journal:
        #启用或禁用持久性日志以确保数据文件保持有效和可恢复
        enabled: true
processManagement:
  #启用在后台运行mongos或mongod进程的守护进程模式
  fork: true
net:
  #服务实例绑定的IP,默认是localhost
  bindIp: 0.0.0.0

6,启动MongoDB

cd /usr/local/mongodb/mongodb-linux-x86_64-4.0.10
bin/mongod -f ./mongod.conf

出现一下提示表示启动成功 image.png 可以查看下进程是否启动: image.png

7,使用 Navicat 链接

image.png

四、MongoDB语法

1,数据库操作

1.1,创建数据库

  • 可以使用以下命令创建数据库,如果不创建,mongodb默认使用的是 test 库
# 如果存在则使用,如果不存在则创建
use liuqiuyiTest

注意,此时创建完数据库后,使用 show dbs 默认是看不到,因为此时这个数据库还在内存中,只有在我们往里面创建集合或者插入文档的情况下,mongodb 才会将这个库写入到磁盘中

db.liuqiuyiTest.insert({"name":"liuqiuyi"});

在使用 show dbs 命令就能看到这个数据库了 image.png

1.2,删除数据库

可以使用以下命令删除数据库:

db.dropDatabase()

删除当前数据库,默认为 test,你可以使用 db 命令查看当前数据库名。 image.png 再次查看发现刚刚创建的数据库被删除了 image.png

2,集合操作

集合的创建分为 显式创建 和 隐式创建:

  • 显式创建:直接使用命令创建集合
  • 隐式创建:创建文档的时候顺带创建集合

2.1 显式创建集合

创建一个 collA 的集合

db.createCollection("collA")

可以通过以下命令查询创建的集合

show collections;

2.2 隐式的创建集合

插入文档的同时,会隐式的创建集合,例如:

db.collB.insert({"name":"liuqiuyi"})

此时查看db中的所有集合,发现collB 被隐式的创建了 image.png

2.3 删除无用的集合

通过以下命令可以删除集合

# collA 表示集合名
db.collA.drop()

3,文档操作

3.1 插入文档

  • 单条插入文档:
db.collA.insert({"name":"liuqiuyi"});

查看集合中所有文档可以到,mongoDb会对插入的文档增加一个名为 _id 的主键,当然你也可以自己指定 image.png

  • 批量插入文档:
db.collA.insertMany([{"name":"张三"},{"name":"李四"}]) 

3.2 查询文档

  • 查询集合中所有的文档
db.collA.find();
  • 带条件查询文档
# 查询集合文档中,name=liuqiuyi的
db.collA.find({"name":"liuqiuyi"});
  • 如果有多个满足条件的,只取第一条,类似于关系型数据库中的 limit 1 ,可以使用 findOne
db.collA.findOne({"name":"liuqiuyi"});
  • 如果一个文档中有很多字段,我只想查询出某一个字段,其它字段不显示,可以在查询语句后面写上对应的条件,例如:
# 这里表示查询 name=liuqiuyi 的文档,只显示 name 字段,注意 1 是数字类型
db.collA.find({"name":"liuqiuyi"},{"name":1});

3.3 更新文档

  • 覆盖修改:修改某个字段之后,会将之前整个文档替换为修改后的字段

image.png 我们将第一条的数据,age 修改为 22

# 将 _id = 5f5e1ece6db32411440004a3 的文档,age 值修改为 22,注意要使用ObjectId()
db.collA.update({_id:ObjectId("5f5e1ece6db32411440004a3")},{"age":22});

image.png

  • **局部修改:**只修改某个字段的值,其它字段不受影响
# 和刚刚的语句类似,只是加了个 $set 标识
db.collA.update({_id:ObjectId("5f5e1ece6db32411440004a3")},{$set:{"age":23}});

image.png

  • 如果更新条件有多个符合的文档,某认只会更新第一个,如果想将所有满足条件的全部更新,需要加上 multi:true 参数
# 将文档中 name = liuqiuyi 的所有数据,age 修改为 25 ,并且不影响其它字段的值
db.collA.update({"name":"liuqiuyi"},{$set:{"age":25}},{multi:true});
  • 如果想对某一个数值字段进行增加或者减少,可以使用 $inc 运算符实现
# id 为 5f5e1ece6db32411440004a3 的 age 字段进行 +1 的操作
db.collA.update({"_id":ObjectId("5f5e1ece6db32411440004a3")},{$inc:{age:1}});

如果是减少,则为 {$inc:{age:-1}}

3.4 删除文档

  • 根据 _id 删除某一个文档
db.collA.remove({"_id":ObjectId("5f5e1f1c6db32411440004a4")})

如果删除的条件对应多个文档,也可以直接删除掉,不需要添加额外的参数

  • 删除所有的文档
db.collA.remove({});

3.5 统计查询

  • 统计当前集合中有多少个文档
db.collA.count();

也可以带条件统计

# 统计当前集合中,name = liuqiuyi 的文档的个数
db.collA.count({"name":"liuqiuyi"});

3.6 分页查询

集合中有4个文档 image.png

  • 使用 limit 参数查询前几条数据
# 查询前两条数据
db.collA.find().limit(2);

如果我想查询第3、4两条数据,那么只使用 limit 就无法完成了,这时需要用到 skip 关键字

  • 跳过前两条,查询第3、4条数据
db.collA.find().skip(2).limit(2);

3.7 排序查询

  • 单条件排序查询
# 按照 age 字段升序
db.collA.find().sort({"age":1})

如果是降序,则将排序条件修改为:sort({"age":-1})

  • 多条件排序
# 先按照 age 升序,在按照 name 进行降序
db.collA.find().sort({"age":1},{"name":-1})

3.8 正则表达式查询

mongoDB 中可以通过 JS 的正则表达式写法查询,常用的有:

  • 查询包含某一字段的文档
# 查询文档中name字段包含 liu 这个字段的,注意不要使用引号
db.collA.find({"name":/liu/});
  • 查询某一字段开头的文档
# 查询文档中 name 字段 以 张 开头的
db.collA.find({"name":/^张/});
  • 查询某一字段结尾的文档
# 查询文档中name字段以 yi 结尾的
db.collA.find({"name":/yi$/});
  • 忽略大小写匹配
# 查询文档中name字段包含 liu 这个字段的, i 表示 忽略大小写
db.collA.find({"name":/liuqiuyi/i});

3.9 比较查询

# 查询文档中 age 值 大于 20 的
db.collA.find({"age":{$gt:20}});

常见的运算符有:

运算符含义
$gt大于
$lt小于
$gte大于等于
$lte小于等于
$ne不等于

3.10 包含查询

包含查询使用 $in 操作符,类似关系型数据库中的in关键字

# 在文档中查找 name 在 in 条件的
db.collA.find({"name":{$in:["liuqiuyi","Liuqiuyi","张三"]}})

不包含使用 $nin 操作符

db.collA.find({"name":{$nin:["liuqiuyi","Liuqiuyi","张三"]}})

3.11 条件连接查询

mongodb 是不支持 join 查询的,所以这里只介绍两个连接查询,and 和 or

  • and 多条件查询
# 查询 age >= 22 and age <= 24
db.collA.find({$and:[{"age":{$gte:22}},{"age":{$lte:24}}]});

# 查询 name = liuqiuyi and age = 25
db.collA.find({$and:[{"name":"liuqiuyi"},{"age":25}]})
  • or 条件查询
# 查询 name = Liuqiuyi or name = liuqiuyi
db.collA.find({$or:[{"name":"Liuqiuyi"},{"name":"liuqiuyi"}]});

五、索引

mongoDB 和 mysql 类似,也是可以对集合中的文档创建索引的,以此来加快查询速度

5.1 索引的类型

单字段索引

  • mongo支持在文档的单个字段上创建 升序/降序 索引,这种索引被称为单字段索引。对于单个字段的索引,索引键的排序顺序并不重要。因为mongoDB可以在任何方向上遍历索引

复合索引

  • 在多个字段上创建索引,就是复合索引。复合索引中列出的字段顺序就是排序的顺序。例如:{name: 1,age: -1} 表示先按照 name 正序排序,在按照 age 倒序排序

其它索引

  • 文本索引
  • 哈希索引

其它索引本次不讨论

5.2 索引的管理

索引的查看

通过如下命令查看集合中所有的索引:

# 查询集合中所有的索引。collA 是集合名
db.collA.getIndexes();

可以看到和mysql一样,主键默认有一个索引 image.png 上面的参数表示的含义为:

字段名含义
VmongoDb 的索引版本号
key_id 表示对应的索引列,后面的 1 表示正序,如果是 -1 表示降序
name索引名称。默认为字段加上 _
nsname space ,表示对应的集合

索引的创建

  • 创建索引的语法为:
# 在 collA 集合中对 name 字段创建一个 升序索引。如果为 -1 就是降序索引
db.collA.createIndex({"name":1});

创建完成后在次查询集合中所有的索引

db.collA.getIndexes();

image.png

  • 也可以创建符合索引
# 对 collA 集合创建复合索引,先按照 age 升序,在按照 date 降序
db.collA.createIndex({"age":1,"date":-1});
  • 创建索引时的更多选项

创建索引时,可以指定 options ,常见的 options 参数列表有:

参数参数类型描述
backgroundBoolean建索引过程会阻塞其它数据库操作,background可指定以后台方式创建索引,默认值为 false
uniqueBoolean建立的索引是否唯一。指定为true创建唯一索引。默认值为false
expireAfterSecondsint指定一个以秒为单位的数值,完成 TTL设定,设定集合的生存时间
weightsdocument索引权重值,数值在 1 到 99,999 之间,表示该索引相对于其他索引字段的得分权重

以 unique 参数举例:

# 对 collA 集合中的 name 字段创建 升序索引,并且是唯一索引
db.collA.createIndex({"name":1},{"unique":true});

索引的删除

  • 删除指定的索引
# 删除指定的索引。这里删除的是 collA 集合中 name = 1 的索引
db.collA.dropIndex({"name":1})

也可以通过索引名称删除对应的索引

# 先查询集合中所有的索引
db.collA.getIndexes();

image.png

# 删除指定名称的索引
db.collA.dropIndex("age_-1")
  • 删除所有的索引
# 删除 collA 集合中所有的索引
db.collA.dropIndexes();

但是 _id 的索引是无法删除的

5.3 索引的使用

执行计划

类似于 mysql ,我们也可以使用 explain 关键字来查看我们的查询语句是否使用了索引

# 查询 collA 集合中,age=24 and name=Liuqiuyi 的文档,并使用explain 查看执行计划
db.collA.find({$and:[{"age":24},{"name":"Liuqiuyi"}]}).explain();

image.png 上图中查看到我们并未使用索引,那么我们加上索引之后,在使用 explain 查询一下

# 对 collA 集合创建复合索引,按照age升序,name升序
db.collA.createIndex({"age":1,"name":1});

执行刚刚的查询语句,查看执行计划 image.png

六、和 java 整合

见另一篇文档 mongoDB和java整合