Go教程

MongoDB 5.0.5

本文主要是介绍MongoDB 5.0.5,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

MongoDB 5.0.5

  • 一、MongoDB 简介
    • 1.1、说明
    • 1.2、特点
    • 1.3、应用场景
    • 1.5、安装
  • 二、MongoDB 概念解析
    • 2.1、库(DataBase)
    • 2.2、集合(Collection)
    • 2.3、文档(Document)
    • 2.4、关系总结
  • 三、基本操作
    • 3.1、数据库
    • 3.2、集合
    • 3.3、文档
  • 四、文档查询
    • 4.1、语法
    • 4.2、MongoDB 与 RDBMS Where 语句比较
    • 4.3、AND
    • 4.4、OR
    • 4.5、AND 和 OR 联合
    • 4.6、数组中查询
    • 4.7、模糊查询
    • 4.8、排序
    • 4.9、分页
    • 4.10、总条数
    • 4.11、去重
    • 4.12、指定返回字段
  • 五、MongoDB $type 操作符
    • 5.1、说明
    • 5.2、使用
  • 六、索引
    • 6.1、介绍
    • 6.2、索引原理
    • 6.3、操作
    • 6.4、复合索引
  • 七、聚合
    • 7.1、语法
    • 7.2、实例
    • 7.3、常见聚合表达式
  • 八、SpringBoot整合MongoDB
    • 8.1、环境搭建
    • 8.2、集合操作
    • 8.3、文档操作
      • 8.3.1、添加实体
      • 8.3.2、相关注解
      • 8.3.3、添加文档
      • 8.3.4、查询文档
      • 8.3.5、更新文档
      • 8.3.5、删除文档
  • 九、MongoDB 复制(副本集)
    • 9.1、说明
    • 9.2、什么是复制
    • 9.3、MongoDB复制原理
    • 9.4、Automatic Failover(自动故障转移)
  • 十、分片集群
    • 10.1、说明
    • 10.2、架构

一、MongoDB 简介

文档地址:https://docs.mongodb.com/manual/

1.1、说明

MongoDB 是一个基于分布式文件存储的数据库。由 C++ 语言编写。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案

MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。他支持的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型 。Mongo最大的特点是他支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引

总结: mongoDB 是一个非关系型文档数据库

1.2、特点

  • 面向集合存储,易存储对象类型的数据
  • 支持查询,以及动态查询
  • 支持RUBY,PYTHON,JAVA,C++,PHP,C#等多种语言
  • 文件存储格式为BSON(一种JSON的扩展)
  • 支持复制和故障恢复和分片
  • 支持事务支持
  • 索引 聚合 关联…

1.3、应用场景

  • 游戏应用:使用云数据库MongoDB作为游戏服务器的数据库存储用户信息。用户的游戏装备、积分等直接以内嵌文档的形式存储,方便进行查询与更新。
  • 物流应用:使用云数据库MongoDB存储订单信息,订单状态在运送过程中会不断更新,以云数据库MongoDB内嵌数组的形式来存储,一次查询就能将订单所有的变更读取出来,方便快捷且一目了然。
  • 社交应用:使用云数据库MongoDB存储用户信息以及用户发表的朋友圈信息,通过地理位置索引实现附近的人、地点等功能。并且,云数据库MongoDB非常适合用来存储聊天记录,因为它提供了非常丰富的查询,并在写入和读取方面都相对较快。
  • 视频直播:使用云数据库MongoDB存储用户信息、礼物信息等。
  • 大数据应用:使用云数据库MongoDB作为大数据的云存储系统,随时进行数据提取分析,掌握行业动态。

1.5、安装

安装部署地址:https://blog.csdn.net/qq_37242720/article/details/122680686

二、MongoDB 概念解析

不管我们学习什么数据库都应该学习其中的基础概念,在mongodb中基本的概念是文档、集合、数据库。

2.1、库(DataBase)

mongodb中的库就类似于传统关系型数据库中库的概念,用来通过不同库隔离不同应用数据`。mongodb中可以建立多个数据库。每一个库都有自己的集合和权限,不同的数据库也放置在不同的文件中。默认的数据库为"test",数据库存储在启动指定的data目录中。

2.2、集合(Collection)

集合就是 MongoDB 文档组,类似于 RDBMS (关系数据库管理系统:Relational Database Management System)中的表的概念。

集合存在于数据库中,一个库中可以创建多个集合。每个集合没有固定的结构,这意味着你在对集合可以插入不同格式和类型的数据,但通常情况下我们插入集合的数据都会有一定的关联性。

2.3、文档(Document)

文档集合中一条条记录,是一组键值(key-value)对(即 BSON)。MongoDB 的文档不需要设置相同的字段,并且相同的字段不需要相同的数据类型,这与关系型数据库有很大的区别,也是 MongoDB 非常突出的特点。

2.4、关系总结

SQL术语/概念MongoDB术语/概念解释/说明
databasedatabase数据库
tablecollection数据库表/集合
rowdocument数据记录行/文档
columnfield数据字段/域
indexindex索引
table joins表连接,MongoDB不支持
primary keyprimary key主键,MongoDB自动将_id字段设置为主键

三、基本操作

3.1、数据库

## 查看有权限查看的所有的数据库命令
# 方法一
show databases; 
# 方法二
show dbs;

## 选择和创建数据库的语法格式,use代表创建并使用,当库中没有数据时默认不显示这个库
use 数据库名称

## 查看当前正在使用的数据库命令
db

## 删除数据库,主要用来删除已经持久化的数据库,默认删除当前选中的库
db.dropDatabase()

MongoDB 中默认的数据库为 test,如果你没有创建新的数据库,集合将存放在 test 数据库中。

数据库名可以是满足以下条件的任意UTF-8字符串。

  • 不能是空字符串("")。
  • 不得含有’ '(空格)、.、$、/、\和\0 (空字符)。
  • 应全部小写。
  • 最多64字节。

有一些数据库名是保留的,可以直接访问这些有特殊作用的数据库。

  • admin
    从权限的角度来看,这是"root"数据库。要是将一个用户添加到这个数据库,这个用户自动继承所有数据库的权限。一些特定的服务器端命令也只能从这个数据库运行,比如列出所有的数据库或者关闭服务器。
  • local
    这个数据永远不会被复制,可以用来存储限于本地单台服务器的任意集合
  • config
    当Mongo用于分片设置时,config数据库在内部使用,用于保存分片的相关信息。

注意: 在 MongoDB 中,集合只有在内容插入后才会创建! 就是说,创建集合(数据表)后要再插入一个文档(记录),集合才会真正创建。

3.2、集合

集合,类似关系型数据库中的表。可以显示的创建,也可以隐式的创建。

##  查看当前库中的集合(表):show tables命令
# 方式一
show collections
# 方式二
show tables

## 集合的显式创建
db.createCollection(name, options)
# 参数说明:
# 	name: 要创建的集合名称
# 	options: 可选参数, 指定有关内存大小及索引的选项

## 集合的隐式创建
db.集合名称.insert({"name":"tom"})

## 删除集合 如果成功删除选定集合 则 drop() 方法返回 true 否则返回 false 语法格式:
# 方式一
db.collection.drop()
# 方式二
db.集合名称.drop()

集合的命名规范:

  • 集合名不能是空字符串""。
  • 集合名不能含有\0字符(空字符),这个字符表示集合名的结尾。
  • 集合名不能以"system."开头,这是为系统集合保留的前缀。
  • 用户创建的集合名字不能含有保留字符。有些驱动程序的确支持在集合名里面包含,这是因为某些系统生成的集合中包含该字符。除非你要访问这种系统创建的集合,否则千万不要在名字里出现$

3.3、文档

参考文档:https://docs.mongodb.com/manual/reference/method/

## 插入单条文档
db.集合名称.insert({"name":"xuxiansheng","age":18,"sex":"男"});

## 插入多条文档
db.集合名称.insertMany(
   [ <document 1> , <document 2>, ... ],
   {
 	  writeConcern: 1,//写入策略,默认为 1,即要求确认写操作,0 是不要求。
      ordered: true //指定是否按顺序写入,默认 true,按顺序写入。
   }
)
db.集合名称.insert([
  	{"name":"java","age":18,"sex":"男"},
  	{"name":"go","age":16,"sex":"女"}
]);

## 脚本方式
for(let i=; i<10;i++){
 db.users.insert({"_id":i,"name":"java_"+i,"age":i})
 }

## 查询所有
db.集合名称.find();

## 删除文档
# 参数说明:
- query:可选`删除的文档的条件。
- justOne:可选`如果设为 true 或 1,则只删除一个文档,如果不设置该参数,或使用默认值 false,则删除所有匹配条件的文档。
- writeConcern :可选抛出异常的级别

db.集合名称.remove(
   <query>,
   {
     justOne: <boolean>,
     writeConcern: <document>
   }
)

## 更新文档
# 参数说明:
- query:update的查询条件,类似sql update查询内where后面的。
- updat:update的对象和一些更新的操作符(如$,$inc...)等,也可以理解为sql update查询内set后面的
- upsert:可选,这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入。
- multi:可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。
- writeConcern:可选,抛出异常的级别。
db.集合名称.update(
   <query>,
   <update>,
   {
     upsert: <boolean>,
     multi: <boolean>,
     writeConcern: <document>
   }
);

# 这个更新是将符合条件的全部更新成后面的文档,相当于先删除在更新
db.集合名称.update({"name":"zhangsan"},{name:"11",bir:new date()}) 

# 保留原来数据更新,但是只更新符合条件的第一条数据
db.集合名称.update({"name":"xiaohei"},{$set:{name:"mingming"}})
	
# 保留原来数据更新,更新符合条件的所有数据
- db.集合名称.update({name:”小黑”},{$set:{name:”小明”}},{multi:true})		

# 保留原来数据更新,更新符合条件的所有数据 没有条件符合时插入数据
- db.集合名称.update({name:”小黑”},{$set:{name:”小明”}},{multi:true,upsert:true})

注意:在 mongodb 中每个文档都会有一个_id作为唯一标识,_id默认会自动生成如果手动指定将使用手动指定的值作为_id 的值。

四、文档查询

4.1、语法

MongoDB 查询文档使用 find() 方法。find() 方法以非结构化的方式来显示所有文档。

## find() 方法以非结构化的方式来显示所有文档
# 参数:
# - query:可选,使用查询操作符指定查询条件
# - projection:可选,使用投影操作符指定返回的键。查询时返回文档中所有键值, 只需省略该参数即可(默认省略)。
db.集合名称.find(query, projection)

## pretty() 方法以格式化的方式来显示所有文档。
db.集合名称.find().pretty()

4.2、MongoDB 与 RDBMS Where 语句比较

如果你熟悉常规的 SQL 数据,通过下表可以更好的理解 MongoDB 的条件语句查询:

操作格式范例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

4.3、AND

db.集合名称.find({key1:value1, key2:value2,...}).pretty()

类似于 WHERE 语句:WHERE key1=value1 AND key2=value2

4.4、OR

MongoDB OR 条件语句使用了关键字 $or,语法格式如下:

db.集合名称.find(
   {
      $or: [
         {key1: value1}, {key2:value2}
      ]
   }
).pretty()

类似于 WHERE 语句:WHERE key1=value1 or key2=value2

4.5、AND 和 OR 联合

db.集合名称.find(
	{"age": {$gt:50}, $or: [{"name": "java"},{"name": "MongoDB"}]}
).pretty();

4.6、数组中查询

-- 测试数据
db.users.insert({"_id":100, "name":"java_100", "age": 100, "likes":["抽烟", "喝酒", "烫头"]})

-- 执行数组查询
db.users.find({likes:"抽烟"})

-- $size 按照数组长度查询
> db.users.find({likes:{$size:3}});

4.7、模糊查询

db.users.find({likes:/烟/});

类似SQL中 where name like “%name%''

注意:在mongoDB中使用正则表达式可以是实现近似模糊查询功能

4.8、排序

## sort 排序  1:升序  -1:降序
db.集合名称.find().sort({name:1,age:1}),

db.users.find().sort({"name": 1, "age":-1})

类似 SQL 语句为:order by name asc, age desc

4.9、分页

db.集合名称.find().sort({条件}).skip(start).limit(rows);

类似于 SQL 语句为:limit start, rows

4.10、总条数

db.集合名称.count();

db.users.find({"name":/java/}).count();

类似于 SQL 语句为:select count(id) from ....

4.11、去重

db.集合名称.distinct('字段')

类似于 SQL 语句为:select distinct name from ....

4.12、指定返回字段

db.集合名称.find({条件},{name:1,age:1}) 
- 参数2: 1返回 0不返回 1和0不能同时使用
db.users.find({"name":/java/}, {name:1,age:1}

五、MongoDB $type 操作符

5.1、说明

$type操作符是基于BSON类型来检索集合中匹配的数据类型,并返回结果。

MongoDB 中可以使用的类型如下表所示:

类型数字别名备注
Double1“double”
String2“string”
Object3“object”
Array4“array”
Binary data5“binData”
Undefined6“undefined”不推荐。
Object id7“objectId”
Boolean8“bool”
Date9“date”
Null10“null”
Regular Expression11“regex”
DBPointer12“dbPointer”不推荐。
JavaScript13“javascript”
Symbol14“symbol”不推荐。
JavaScript code with scope15“javascriptWithScope”MongoDB 4.4中已弃用。
32-bit integer16“int”
Timestamp17“timestamp”
64-bit integer18“timestamp”
Decimal12819“timestamp”
Min key-1“timestamp”Query with -1.
Max key127“timestamp”

5.2、使用

>db.col.insert({
    title: 'PHP 教程', 
    description: 'PHP 是一种创建动态交互性站点的强有力的服务器端脚本语言。',
    by: '徐先生',
    url: 'http://www.java521.com',
    tags: ['php'],
    likes: 200
})

>db.col.insert({
	title: 'Java 教程', 
    description: 'Java 是由Sun Microsystems公司于1995年5月推出的高级程序设计语言。',
    by: '徐先生',
    url: 'http://www.runoob.com',
    tags: ['java'],
    likes: 150
})

>db.col.insert({
	title: 'MongoDB 教程', 
    description: 'MongoDB 是一个 Nosql 数据库',
    by: '徐先生',
    url: 'http://www.java521.com',
    tags: ['mongodb'],
    likes: 100
})

>db.col.insert({
	title: 666, 
    description: 'MySQL  是一个 关系型 数据库',
    by: '徐先生',
    url: 'http://www.java521.com',
    tags: ['mongodb'],
    likes: 100
})

-- 使用find()命令查看数据
> db.col.find().pretty();

## 如果想获取 "col" 集合中 title 为 String 的数据,你可以使用以下命令:
# 方式一
db.col.find({"title" : {$type : 2}}).pretty();
# 方式二
db.col.find({"title" : {$type : 'string'}}).pretty();

六、索引

6.1、介绍

索引通常能够极大的提高查询的效率,如果没有索引,MongoDB在读取数据时必须扫描集合中的每个文件并选取那些符合查询条件的记录。

这种扫描全集合的查询效率是非常低的,特别在处理大量的数据时,查询可以要花费几十秒甚至几分钟,这对网站的性能是非常致命的。

索引是特殊的数据结构,索引存储在一个易于遍历读取的数据集合中,索引是对数据库表中一列或多列的值进行排序的一种结构

文档地址:https://docs.mongodb.com/manual/indexes/

6.2、索引原理

下图说明了使用索引选择和排序匹配文档的查询:
在这里插入图片描述
从根本上说,MongoDB 中的索引与其他数据库系统中的索引类似。MongoDB在集合级别定义索引,并支持 MongoDB集合中文档的任何字段或子字段的索引。

6.3、操作

## 创建索引 
# Key 值为你要创建的索引字段
# 1 按升序创建索引,-1按降序来创建索引
db.集合名称.createIndex(keys, options)
db.集合名称.createIndex({"title":1,"description":-1})

createIndex()接收可选参数,可选参数列表如下:

ParameterTypeDescription
backgroundBoolean建索引过程会阻塞其它数据库操作,background可指定以后台方式创建索引,即增加 “background” 可选参数。 “background” 默认值为false
uniqueBoolean建立的索引是否唯一。指定为true创建唯一索引。默认值为false.
namestring索引的名称。如果未指定,MongoDB的通过连接索引的字段名和排序顺序生成一个索引名称。
dropDupsBoolean**3.0+版本已废弃。**在建立唯一索引时是否删除重复记录,指定 true 创建唯一索引。默认值为 false.
sparseBoolean对文档中不存在的字段数据不启用索引;这个参数需要特别注意,如果设置为true的话,在索引字段中不会查询出不包含对应字段的文档.。默认值为 false.
expireAfterSecondsinteger指定一个以秒为单位的数值,完成 TTL设定,设定集合的生存时间。
vindex version索引的版本号。默认的索引版本取决于mongod创建索引时运行的版本。
weightsdocument索引权重值,数值在 1 到 99,999 之间,表示该索引相对于其他索引字段的得分权重。
default_languagestring对于文本索引,该参数决定了停用词及词干和词器的规则的列表。 默认为英语
language_overridestring对于文本索引,该参数指定了包含在文档中的字段名,语言覆盖默认的language,默认值为 language.
## 查看集合索引
db.集合名称.getIndexes()

## 查看集合索引大小
db.集合名称.totalIndexSize()

## 删除集合所有索引
db.集合名称.dropIndexes()

## 删除集合指定索引 
db.集合名称.dropIndex("索引名称")

6.4、复合索引

说明:一个索引的值是由多个 key 进行维护的索引的称之为复合索引。

db.集合名称.createIndex({"title":1,"description":-1})

注意:mongoDB 中复合索引和传统关系型数据库一致都是最左前缀原则

七、聚合

MongoDB 中聚合(aggregate)主要用于处理数据(诸如统计平均值,求和等),并返回计算后的数据结果。类似 SQL 语句中的 count(*)。

7.1、语法

MongoDB中聚合的方法使用aggregate(),aggregate() 方法的基本语法格式:

db.集合名称.aggregate(AGGREGATE_OPERATION);

7.2、实例

db.mycol.insertMany([
	{
	   _id: 1,
	   title: 'MongoDB Overview', 
	   description: 'MongoDB is no sql database',
	   by_user: 'runoob.com',
	   url: 'http://www.java521.com',
	   tags: ['mongodb', 'database', 'NoSQL'],
	   likes: 100
	},
	{
	   _id: 2,
	   title: 'NoSQL Overview', 
	   description: 'No sql database is very fast',
	   by_user: 'runoob.com',
	   url: 'http://www.java521.com',
	   tags: ['mongodb', 'database', 'NoSQL'],
	   likes: 10
	},
	{
	   _id: 3,
	   title: 'Neo4j Overview', 
	   description: 'Neo4j is no sql database',
	   by_user: 'Neo4j',
	   url: 'http://www.baidu.com',
	   tags: ['neo4j', 'database', 'NoSQL'],
	   likes: 750
	}
])

## 通过以上集合计算每个作者所写的文章数,使用aggregate()计算
db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : 1}}}])

以上实例类似sql语句:
select by_user, count(*) from mycol group by by_user

7.3、常见聚合表达式

表达式描述实例
$sum计算总和。db.mycol.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : "by_user", num_tutorial : { s u m : " sum : " sum:"likes"}}}])
$avg计算平均值db.mycol.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : "by_user", num_tutorial : { a v g : " avg : " avg:"likes"}}}])
$min获取集合中所有文档对应值得最小值。db.mycol.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : "by_user", num_tutorial : { m i n : " min : " min:"likes"}}}])
$max获取集合中所有文档对应值得最大值。db.mycol.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : "by_user", num_tutorial : { m a x : " max : " max:"likes"}}}])
$push将值加入一个数组中,不会判断是否有重复的值。db.mycol.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : "by_user", url : { p u s h : " push: " push:"url"}}}])
$addToSet将值加入一个数组中,会判断是否有重复的值,若相同的值在数组中已经存在了,则不加入。db.mycol.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : "by_user", url : { a d d T o S e t : " addToSet : " addToSet:"url"}}}])
$first根据资源文档的排序获取第一个文档数据。db.mycol.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : "by_user", first_url : { f i r s t : " first : " first:"url"}}}])
$last根据资源文档的排序获取最后一个文档数据db.mycol.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : "by_user", last_url : { l a s t : " last : " last:"url"}}}])

八、SpringBoot整合MongoDB

8.1、环境搭建

创建spring boot 项目springboot-mongodb
添加依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-mongodb</artifactId>
    </dependency>
    <!--lombok插件-->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
        <exclusions>
            <exclusion>
                <groupId>org.junit.vintage</groupId>
                <artifactId>junit-vintage-engine</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
</dependencies>

配置

# 应用名称
spring.application.name=springboot-mongodb
# 应用服务 WEB 访问端口
server.port=8080

# mongodb 没有开启任何安全协议
# mongodb(协议)://192.168.200.128(主机):27017(端口)/users(库名)
spring.data.mongodb.uri=mongodb://192.168.200.128:27017/users

# mongodb 存在密码
#spring.data.mongodb.host=192.168.200.128
#spring.data.mongodb.port=27017
#spring.data.mongodb.database=users
#spring.data.mongodb.username=root
#spring.data.mongodb.password=root

8.2、集合操作

···java
@SpringBootTest
public class CollectionTest {

@Autowired
private MongoTemplate mongoTemplate;

//创建集合
@Test
public void createCollection() {
    mongoTemplate.createCollection("users");
}

//删除集合
@Test
public void dropCollection() {
    mongoTemplate.dropCollection("users");
}

}
···

8.3、文档操作

8.3.1、添加实体

@Data
@Document("users")
public class User {
    @Id
    private Integer id;
    
    @Field
    private String name;

    @Field
    private Integer age;

    @Field
    private Date bir;
}

8.3.2、相关注解

  • @Document
    • 修饰范围: 用在类上
    • 作用: 用来映射这个类的一个对象为 mongo 中一条文档数据
    • 属性:(value 、collection )用来指定操作的集合名称
  • @Id
    • 修饰范围: 用在成员变量、方法上
    • 作用: 用来将成员变量的值映射为文档的_id 的值
  • @Field
    • 修饰范围: 用在成员变量、方法上
    • 作用: 用来将成员变量以及值映射为文档中一个key、value对
    • 属性: ( name,value)用来指定在文档中 key 的名称,默认为成员变量名
  • @Transient
    • 修饰范围: 用在成员变量、方法上
    • 作用 : 用来指定改成员变量,不参与文档的序列化

8.3.3、添加文档

添加一条文档

@Test
public void insertOrSave() {
    User user = new User();
    user.setId(1);
    user.setAge(20);
    user.setName("徐先生");
    user.setBir(new Date());
    //insert不存在时添加, 存在时报错
    //User saveUser = mongoTemplate.insert(user);
    //save不存在时添加, 存在时更新
    User saveUser = mongoTemplate.save(user);
    System.out.println(saveUser);
}

添加多条文档

@Test
public void batchInsertOrSave() {
    List<User> list = new ArrayList<>();
    for (int i = 2; i <= 10; i++) {
        User user = new User();
        user.setId(i);
        user.setAge(18 + i);
        user.setName("徐先生" + i);
        user.setBir(new Date());
        list.add(user);

    }
    /*
        insert不存在时添加, 存在时报错
        参数一:批量数据
        参数二:放入哪个集合
     */
    Collection<User> insert = mongoTemplate.insert(list, User.class);
    System.out.println(insert);
}
  • insert
    插入重复数据时:insertDuplicateKeyException提示主键重复;save对已存在的数据进行更新。
  • save
    批处理操作时:insert可以一次性插入整个数据,效率较高;save需遍历整个数据,一次插入或更新,效率较低。

8.3.4、查询文档

在这里插入图片描述

//文档查询
@Test
public void findAll() {
    //1.查询所有
    //List<User> list = mongoTemplate.findAll(User.class);
    List<User> list = mongoTemplate.findAll(User.class, "users");
    list.forEach(System.out::println);


    //2.基于id 查询一条文档
    User user = mongoTemplate.findById(1, User.class);
    System.out.println(user);

    //3.添加查询
    //参数一:查询条件  参数二:查询类型
    List<User> userList = mongoTemplate.find(new Query(), User.class);
    userList.forEach(System.out::println);

    //4.等值查询
    List<User> userList1 = mongoTemplate.find(Query.query(Criteria.where("name").is("徐先生")), User.class);
    userList1.forEach(System.out::println);

    System.out.println("========比较查询=========");
    //5.比较查询 > gt  < lt  >= gte  <= lte
    List<User> userList2 = mongoTemplate.find(Query.query(Criteria.where("age").lt(25)), User.class);
    userList2.forEach(System.out::println);
    System.out.println("=================");
    List<User> userList3 = mongoTemplate.find(Query.query(Criteria.where("age").gt(25)), User.class);
    userList3.forEach(System.out::println);
    System.out.println("=================");
    List<User> userList4 = mongoTemplate.find(Query.query(Criteria.where("age").lte(25)), User.class);
    userList4.forEach(System.out::println);
    System.out.println("=================");
    List<User> userList5 = mongoTemplate.find(Query.query(Criteria.where("age").gte(25)), User.class);
    userList5.forEach(System.out::println);

    System.out.println("========and=========");
    List<User> userList6 = mongoTemplate.find(Query.query(Criteria.where("name").is("徐先生4").and("age").is(22)), User.class);
    userList6.forEach(System.out::println);

    System.out.println("========or=========");
    Criteria criteria = new Criteria().orOperator(
	    Criteria.where("name").is("徐先生4"), 
	    Criteria.where("name").is("徐先生5")
    );
    List<User> userList7 = mongoTemplate.find(Query.query(criteria), User.class);
    userList7.forEach(System.out::println);

    System.out.println("=========and or========");
    Criteria criteria1 = new Criteria().and("age").is(20).orOperator(
            Criteria.where("name").is("徐先生3"),
            Criteria.where("name").is("徐先生4"));
    List<User> userList8 = mongoTemplate.find(Query.query(criteria1), User.class);
    userList8.forEach(System.out::println);

    System.out.println("=========sort 排序========");
    Query query = new Query();
    query.with(Sort.by(Sort.Order.desc("age")));//desc 降序  asc 升序
    List<User> userList9 = mongoTemplate.find(query, User.class);
    userList9.forEach(System.out::println);

    System.out.println("========skip limit 分页=========");
    Query queryPage = new Query();
    queryPage.with(Sort.by(Sort.Order.desc("age")))//desc 降序  asc 升序
            .skip(0) //起始条数
            .limit(4); //每页显示记录数
    List<User> userList10 = mongoTemplate.find(queryPage, User.class);
    userList10.forEach(System.out::println);

    System.out.println("========count 总条数=========");
    long count = mongoTemplate.count(new Query(), User.class);
    System.out.println(count);

    System.out.println("========distinct 去重=========");
    //参数 1:查询条件 参数 2: 去重字段  参数 3: 操作集合  参数 4: 返回类型
    List<Integer> age = mongoTemplate.findDistinct(new Query(), "age",
            User.class, Integer.class);
    age.forEach(System.out::println);

    System.out.println("========使用 json 字符串方式查询=========");
    Query query2 = new BasicQuery("{$or:[{name:'徐先生8'},{name:'徐先生9'}]}", "{name:1}");
    List<User> userList11 = mongoTemplate.find(query2, User.class);
    userList11.forEach(System.out::println);
}

8.3.5、更新文档

@Test
public void  update(){
    //1.更新条件
    Query query = Query.query(Criteria.where("age").is(22));
    //2.更新内容
    Update update = new Update();
    update.set("name","徐先生, 您好啊~");

    //单条更新
    UpdateResult updateResult = mongoTemplate.updateFirst(query, update, User.class);
    System.out.println("匹配条数:" + updateResult.getMatchedCount());
    //多条更新
    //UpdateResult updateResult = mongoTemplate.updateMulti(query, update, User.class);
    //System.out.println("修改条数:" + updateResult.getModifiedCount());
    //更新插入
    //UpdateResult updateResult = mongoTemplate.upsert(query, update, User.class);
    //System.out.println("插入id_:" + updateResult.getUpsertedId());
}

8.3.5、删除文档

@Test
public void testDelete() {
    //条件删除
    DeleteResult result = mongoTemplate.remove(Query.query(Criteria.where("name").is("徐先生")), User.class);
    System.out.println(result);

    //删除所有
    DeleteResult deleteResult = mongoTemplate.remove(new Query(), User.class);
    System.out.println(deleteResult);
}

九、MongoDB 复制(副本集)

9.1、说明

文档地址:https://docs.mongodb.com/manual/replication/

MongoDB复制是将数据同步在多个服务器的过程。

复制提供了数据的冗余备份,并在多个服务器上存储数据副本,提高了数据的可用性, 并可以保证数据的安全性。

复制还允许您从硬件故障和服务中断中恢复数据。

9.2、什么是复制

  • 保障数据的安全性
  • 数据高可用性 (24*7)
  • 灾难恢复
  • 无需停机维护(如备份,重建索引,压缩)
  • 分布式读取数据

9.3、MongoDB复制原理

mongodb的复制至少需要两个节点。其中一个是主节点(Primary),负责处理客户端请求,其余的都是从节点(Secondary),负责复制主节点上的数据。

mongodb各个节点常见的搭配方式为:一主一从、一主多从。

主节点记录在其上的所有操作oplog,从节点定期轮询主节点获取这些操作,然后对自己的数据副本执行这些操作,从而保证从节点的数据与主节点一致。

MongoDB复制结构图如下所示:
在这里插入图片描述
以上结构图中,客户端从主节点读取数据,在客户端写入数据到主节点时, 主节点与从节点进行数据交互保障数据的一致性。

9.4、Automatic Failover(自动故障转移)

当主节点与集合中的其他成员通信的时间超过配置的electionTimeoutMillis 时间段(默认为 10 秒)时,符合条件的辅助节点会调用选举来提名自己为新的主节点。集群尝试完成新主节点的选举并恢复正常操作。
在这里插入图片描述
在选举成功完成之前,副本集无法处理写入操作。如果将此类查询配置为在主节点离线时在辅助节点上运行,则副本集可以继续为读取查询提供服务 。

十、分片集群

10.1、说明

文档地址:https://docs.mongodb.com/manual/sharding/

分片(sharding)是指将数据拆分,将其分散存在不同机器的过程,有时也用分区(partitioning)来表示这个概念,将数据分散在不同的机器上,不需要功能强大的大型计算机就能存储更多的数据,处理更大的负载。

分片目的是通过分片能够增加更多机器来应对不断的增加负载和数据,还不影响应用运行。

MongoDB支持自动分片,可以摆脱手动分片的管理困扰,集群自动切分数据做负载均衡。MongoDB分片的基本思想就是将集合拆分成多个块,这些快分散在若干个片里,每个片只负责总数据的一部分,应用程序不必知道哪些片对应哪些数据,甚至不需要知道数据拆分了,所以在分片之前会运行一个路由进程,mongos进程,这个路由器知道所有的数据存放位置,应用只需要直接与mongos交互即可。mongos自动将请求转到相应的片上获取数据,从应用角度看分不分片没有什么区别。

10.2、架构

在这里插入图片描述

  • Shard:
    用于存储实际的数据块,实际生产环境中一个shard server角色可由几台机器组个一个replica set承担,防止主机单点故障
  • Config Server:
    mongod实例,存储了整个 ClusterMetadata。
  • Query Routers:
    前端路由,客户端由此接入,且让整个集群看上去像单一数据库,前端应用可以透明使用。
  • Shard Key:
    片键,设置分片时需要在集合中选一个键,用该键的值作为拆分数据的依据,这个片键称之为(shard key),片键的选取很重要,片键的选取决定了数据散列是否均匀。
这篇关于MongoDB 5.0.5的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!