【SpringBoot高级篇】SpringBoot集成MongDB数据库

  • MongoDB是什么 ?
    • 主要特点
    • MongoDB管理 工具
  • MongoDB 基本概念
    • 数据库
    • 文档(Document)
    • 集合
      • 合法的集合名
      • capped collections
    • 元数据
  • MongoDB 数据类型
    • ObjectId
    • 字符串
    • 时间戳
    • 日期
  • MongoDB基本命令
    • MongoDB 创建数据库
      • 语法
      • 实例
    • MongoDB 删除数据库
      • 语法
      • 实例
      • 删除集合
    • MongoDB 创建集合
      • 语法
      • 实例
    • MongoDB 删除集合
      • 语法
      • 实例
    • MongoDB 插入文档
      • 语法
      • 实例
    • MongoDB 更新文档
      • update() 方法
        • 语法
        • 实例
      • save() 方法
        • 语法
        • 实例
    • MongoDB 删除文档
      • 语法
      • 实例
      • 注意
    • MongoDB 查询文档
      • 语法
        • MongoDB 与 RDBMS Where 语句比较
        • MongoDB AND 条件
        • MongoDB OR 条件
          • 实例
        • AND 和 OR 联合使用
  • docker 部署 mongodb
    • 拉取镜像
    • docker 安装 mongodb
    • 进入容器.
    • `mongodb`的使用
      • 用户的创建
      • 创建用户
      • 数据库的建立
    • mongo 是否正常启动的校验
    • 远程连接的开启
  • 基于MongoTemplate 开发CRUD
    • 1、引入springboot mongo依赖
    • 2、mongo的IP和端口
    • 3、使用mongoTemplate
      • User
      • 常用方法
      • 测试
      • 测试
  • 基于MongoRepository开发CRUD
    • 添加Repository类
    • 测试
  • 多数据源 MongoDB 的使用
    • pom
    • yml
    • MongoConfig
    • Person
    • 测试

MongoDB是什么 ?

  • MongoDB 是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统。
  • 在高负载的情况下,添加更多的节点,可以保证服务器性能。
  • MongoDB 旨在为WEB应用提供可扩展的高性能数据存储解决方案。
  • MongoDB 将数据存储为一个文档,数据结构由键值(key=>value)对组成。MongoDB 文档类似于 JSON 对象。字段值可以包含其他文档,数组及文档数组。
{user: "admin",    --->key=>valuepwd: "123456",   --->key=>valueroles: [ { role: "userAdminAnyDatabase", db: "admin" } ]}

主要特点

  • MongoDB 是一个面向文档存储的数据库,操作起来比较简单和容易。
  • 你可以在MongoDB记录中设置任何属性的索引 (如:FirstName=“Sameer”,Address=“8 Gandhi Road”)来实现更快的排序。
  • 你可以通过本地或者网络创建数据镜像,这使得MongoDB有更强的扩展性。
  • 如果负载的增加(需要更多的存储空间和更强的处理能力) ,它可以分布在计算机网络中的其他节点上这就是所谓的分片。
  • Mongo支持丰富的查询表达式。查询指令使用JSON形式的标记,可轻易查询文档中内嵌的对象及数组。
  • MongoDb 使用update()命令可以实现替换完成的文档(数据)或者一些指定的数据字段 。
  • Mongodb中的Map/reduce主要是用来对数据进行批量处理和聚合操作。
  • Map和Reduce。Map函数调用emit(key,value)遍历集合中所有的记录,将key与value传给Reduce函数进行处理。
  • Map函数和Reduce函数是使用Javascript编写的,并可以通过db.runCommand或mapreduce命令来执行MapReduce操作。
  • GridFS是MongoDB中的一个内置功能,可以用于存放大量小文件。
  • MongoDB允许在服务端执行脚本,可以用Javascript编写某个函数,直接在服务端执行,也可以把函数的定义存储在服务端,下次直接调用即可。
  • MongoDB支持各种编程语言:RUBY,PYTHON,JAVA,C++,PHP,C#等多种语言。
  • MongoDB安装简单。

MongoDB管理 工具

  • Fang of Mongo – 网页式,由Django和jQuery所构成。
  • Futon4Mongo – 一个CouchDB Futon web的mongodb山寨版。
  • Mongo3 – Ruby写成。
  • MongoHub – 适用于OSX的应用程序。
  • Opricot – 一个基于浏览器的MongoDB控制台, 由PHP撰写而成。
  • Database Master — Windows的mongodb管理工具
  • RockMongo — 最好的PHP语言的MongoDB管理工具,轻量级, 支持多国语言.

MongoDB 基本概念

在mongodb中基本的概念是文档、集合、数据库

SQL术语/概念 MongoDB术语/概念 解释/说明
database database 数据库
table collection 数据库表/集合
row document 数据记录行/文档
column field 数据字段/域
index index 索引
table joins 表连接,MongoDB不支持
primary key primary key 主键,MongoDB自动将_id字段设置为主键

通过下图实例,我们也可以更直观的了解Mongo中的一些概念:

数据库

一个mongodb中可以建立多个数据库。MongoDB的默认数据库为"db",该数据库存储在data目录中。MongoDB的单个实例可以容纳多个独立的数据库,每一个都有自己的集合和权限,不同的数据库也放置在不同的文件中。

> show dbs   # 命令可以显示所有数据的列表。
admin   0.000GB
config  0.000GB
demo    0.000GB
local   0.000GB
> db   # 显示当前数据库对象或集合。
test
> use demo  # 连接到一个指定的数据库。
switched to db demo

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

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

文档(Document)

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

{"site":"www.zysheep.cn", "name":"三月三"}

下表列出了 RDBMS 与 MongoDB 对应的术语:

RDBMS MongoDB
数据库 数据库
表格 集合
文档
字段
表联合 嵌入文档
主键 主键 (MongoDB 提供了 key 为 _id )

需要注意的是:

  1. 文档中的键/值对是有序的。
  2. 文档中的值不仅可以是在双引号里面的字符串,还可以是其他几种数据类型(甚至可以是整个嵌入的文档)。
  3. MongoDB区分类型和大小写。
  4. MongoDB的文档不能有重复的键。
  5. 文档的键是字符串。除了少数例外情况,键可以使用任意UTF-8字符。

文档键命名规范:

  • 键不能含有\0 (空字符)。这个字符用来表示键的结尾。
  • .和$有特别的意义,只有在特定环境下才能使用。
  • 以下划线"_"开头的键是保留的(不是严格要求的)。

集合

集合就是 MongoDB 文档组,类似于 RDBMS (关系数据库管理系统:Relational Database Management System)中的表格。集合存在于数据库中,集合没有固定的结构,这意味着你在对集合可以插入不同格式和类型的数据,但通常情况下我们插入集合的数据都会有一定的关联性。

比如,我们可以将以下不同数据结构的文档插入到集合中:

{"site":"www.baidu.com"}
{"site":"www.zysheep.cn","name":"三月三"}
{"site":"www.zysheep.cn","name":"三月三热爱生活","num":5}

合法的集合名

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

如下实例:

db.col.findOne()

capped collections

Capped collections 就是固定大小的collection。它有很高的性能以及队列过期的特性(过期按照插入的顺序). 有点和 “RRD” 概念类似。Capped collections 是高性能自动的维护对象的插入顺序。它非常适合类似记录日志的功能和标准的 collection 不同,你必须要显式的创建一个capped collection,指定一个 collection 的大小,单位是字节。collection 的数据存储空间值提前分配的。

db.createCollection("mycoll", {capped:true, size:100000})
  • 在 capped collection 中,你能添加新的对象。
  • 能进行更新,然而,对象不会增加存储空间。如果增加,更新就会失败 。
  • 使用 Capped Collection 不能删除一个文档,可以使用 drop() 方法删除 collection 所有的行。
  • 删除之后,你必须显式的重新创建这个 collection。
  • 在32bit机器中,capped collection 最大存储为 1e9( 1X109)个字节。

元数据

数据库的信息是存储在集合中。它们使用了系统的命名空间:

dbname.system.*

在MongoDB数据库中名字空间 .system.* 是包含多种系统信息的特殊集合(Collection),如下:\

集合命名空间 描述
dbname.system.namespaces 列出所有名字空间。
dbname.system.indexes 列出所有索引。
dbname.system.profile 包含数据库概要(profile)信息。
dbname.system.users 列出所有可访问数据库的用户。
dbname.local.sources 包含复制对端(slave)的服务器信息和状态。

MongoDB 数据类型

数据类型 描述
String 字符串。存储数据常用的数据类型。在 MongoDB 中,UTF-8 编码的字符串才是合法的。
Integer 整型数值。用于存储数值。根据你所采用的服务器,可分为 32 位或 64 位。
Boolean 布尔值。用于存储布尔值(真/假)。
Double 双精度浮点值。用于存储浮点值。
Min/Max keys 将一个值与 BSON(二进制的 JSON)元素的最低值和最高值相对比。
Array 用于将数组或列表或多个值存储为一个键。
Timestamp 时间戳。记录文档修改或添加的具体时间。
Object 用于内嵌文档。
Null 用于创建空值。
Symbol 符号。该数据类型基本上等同于字符串类型,但不同的是,它一般用于采用特殊符号类型的语言。
Date 日期时间。用 UNIX 时间格式来存储当前日期或时间。你可以指定自己的日期时间:创建 Date 对象,传入年月日信息。
Object ID 对象 ID。用于创建文档的 ID。
Binary Data 二进制数据。用于存储二进制数据。
Code 代码类型。用于在文档中存储 JavaScript 代码。
Regular expression 正则表达式类型。用于存储正则表达式。

ObjectId

ObjectId 类似唯一主键,可以很快的去生成和排序,包含 12 bytes,含义是:

  • 前 4 个字节表示创建 unix 时间戳,格林尼治时间 UTC 时间,比北京时间晚了 8 个小时
  • 接下来的 3 个字节是机器标识码
  • 紧接的两个字节由进程 id 组成 PID
  • 最后三个字节是随机数

MongoDB 中存储的文档必须有一个 _id 键。这个键的值可以是任何类型的,默认是个 ObjectId 对象

由于 ObjectId 中保存了创建的时间戳,所以你不需要为你的文档保存时间戳字段,你可以通过 getTimestamp 函数来获取文档的创建时间:

> var newObject = ObjectId()
> newObject.getTimestamp()
ISODate("2020-06-02T00:41:51Z")

ObjectId 转为字符串

> newObject.str
5ed5a04fb5ebb889810105cf

字符串

BSON 字符串都是 UTF-8 编码。

时间戳

BSON 有一个特殊的时间戳类型用于 MongoDB 内部使用,与普通的 日期 类型不相关。 时间戳值是一个 64 位的值。其中:

  • 前32位是一个 time_t 值(与Unix新纪元相差的秒数)
  • 后32位是在某秒中操作的一个递增的序数

在单个 mongod 实例中,时间戳值通常是唯一的。在复制集中, oplog 有一个 ts 字段。这个字段中的值使用BSON时间戳表示了操作时间。

BSON 时间戳类型主要用于 MongoDB 内部使用。在大多数情况下的应用开发中,你可以使用 BSON 日期类型。

日期

表示当前距离 Unix新纪元(1970年1月1日)的毫秒数。日期类型是有符号的, 负数表示 1970 年之前的日期。

> var mydate1 = new Date()
> mydate1
ISODate("2020-06-02T00:43:59.056Z")
> typeof mydate1
object

这样创建的时间是日期类型,可以使用 JS 中的 Date 类型的方法。

返回一个时间类型的字符串:

>  var mydate1str = mydate1.toString()
> mydate1str
Tue Jun 02 2020 00:43:59 GMT+0000 (UTC)
>  typeof mydate1str
string

或者

> Date()
Tue Jun 02 2020 00:45:23 GMT+0000 (UTC)

MongoDB基本命令

MongoDB 创建数据库

语法

use DATABASE_NAME

如果数据库不存在,则创建数据库,否则切换到指定数据库。

实例

> use zysheep  # 创建数据库zysheep
switched to db zysheep
> show dbs    # 查看所有数据库
admin   0.000GB
config  0.000GB
demo    0.000GB
local   0.000GB
> db.zysheep.insert({"sate":"zysheep"})
# 创建的数据库 zysheep 并不在数据库的列表中, 要显示它,我们需要向 zysheep 数据库插入一些数据。
WriteResult({ "nInserted" : 1 })
> show dbs
admin    0.000GB
config   0.000GB
demo     0.000GB
local    0.000GB
zysheep  0.000GB
> db  # 查看当前所在数据库
zysheep

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

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

MongoDB 删除数据库

语法

db.dropDatabase()

删除当前数据库,默认为 test,你可以使用 db 命令查看当前数据库名。

实例

以下实例我们删除了数据库 zysheep。

> show dbs  # 查看所有数据库
admin    0.000GB
config   0.000GB
demo     0.000GB
local    0.000GB
zysheep  0.000GB
> db   # 查看当前数据库
zysheep
> db.dropDatabase()  # 删除当前数据库
{ "dropped" : "zysheep", "ok" : 1 }
> show dbs   # 查看是否删除
admin   0.000GB
config  0.000GB
demo    0.000GB
local   0.000GB

删除集合

> show dbs
admin   0.000GB
config  0.000GB
demo    0.000GB
local   0.000GB
> use zysheep
switched to db zysheep
> db.createCollection("zysheep")    # 先创建集合,类似数据库中的表
{ "ok" : 1 }
> show tables  # show collections 命令会更加准确点
zysheep
> db.zysheep.drop()
true
> show tables

MongoDB 创建集合

语法

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

options 可以是如下参数:

字段 类型 描述
capped 布尔 (可选)如果为 true,则创建固定集合。固定集合是指有着固定大小的集合,当达到最大值时,它会自动覆盖最早的文档。 当该值为 true 时,必须指定 size 参数。
autoIndexId 布尔 (可选)如为 true,自动在 _id 字段创建索引。默认为 false。
size 数值 (可选)为固定集合指定一个最大值,以千字节计(KB)。 如果 capped 为 true,也需要指定该字段。
max 数值 (可选)指定固定集合中包含文档的最大数量。

在插入文档时,MongoDB 首先检查固定集合的 size 字段,然后检查 max 字段。

实例

> use demo #创建 demo 数据库
switched to db demo
> db.createCollection("demo") # 创建 demo 集合
{ "ok" : 1 }
> show collections  # 查看已有集合
demo
info
> show tables # 查看已有集合
demo
info
> db.createCollection("mycol", { capped : true, autoIndexId : true, size :
...    6142800, max : 10000 } )   # 创建固定集合 mycol
{"note" : "the autoIndexId option is deprecated and will be removed in a future release","ok" : 1
}
> show tables   # 查看已有集合
demo
info
mycol
> db.myclo2.insert({"name":"三月三"})
# 在 MongoDB 中,你不需要创建集合。当你插入一些文档时,MongoDB 会自动创建集合。
WriteResult({ "nInserted" : 1 })
> show tables
demo
info
myclo2
mycol

MongoDB 删除集合

语法

db.collection.drop()

如果成功删除选定集合,则 drop() 方法返回 true,否则返回 false。

实例

在数据库mydb中,我们可以先通过 show collections 命令查看已存在的集合:

> use demo  # 使用demo数据库
switched to db demo
> show tables  # 查看当前数据库所有集合
demo
info
myclo2
mycol
> db.demo.drop() # 删除demo集合
true
> show tables;
info
myclo2
mycol
>

MongoDB 插入文档

文档的数据结构和 JSON 基本一样。所有存储在集合中的数据都是 BSON 格式。BSON 是一种类似 JSON 的二进制形式的存储格式,是 Binary JSON 的简称。

语法

MongoDB 使用 insert() 或 save() 方法向集合中插入文档,语法如下:

db.COLLECTION_NAME.insert(document)
或
db.COLLECTION_NAME.save(document)
  • save():如果 _id 主键存在则更新数据,如果不存在就插入数据。该方法新版本中已废弃,可以使用 db.collection.insertOne()db.collection.replaceOne() 来代替。
  • insert(): 若插入的数据主键已经存在,则会抛 org.springframework.dao.DuplicateKeyException 异常,提示主键重复,不保存当前数据

3.2 版本之后新增了 db.collection.insertOne() 和 db.collection.insertMany()。

db.collection.insertOne() 用于向集合插入一个新文档,语法格式如下:

# 语法
db.collection.insertOne(<document>,{writeConcern: <document>}
)
# 实例
> var document = db.collection.insertOne({"a": 3})
> document
{"acknowledged" : true,"insertedId" : ObjectId("5ed5a93256fa4269b4e255ff")
}

db.collection.insertMany() 用于向集合插入一个多个文档,语法格式如下:

# 语法
db.collection.insertMany([ <document 1> , <document 2>, ... ],{writeConcern: <document>,ordered: <boolean>}
)
# 实例
> var res = db.collection.insertMany([{"b": 3}, {'c': 4}])
> res
{"acknowledged" : true,"insertedIds" : [ObjectId("5ed5a93f56fa4269b4e25600"),ObjectId("5ed5a93f56fa4269b4e25601")]
}
  • document:要写入的文档。
  • writeConcern:写入策略,默认为 1,即要求确认写操作,0 是不要求。
  • ordered:指定是否按顺序写入,默认 true,按顺序写入。

实例

以下文档可以存储在 MongoDB 的 demo数据库 的 col 集合中:

>db.col.insert({title: 'MongoDB 教程', description: 'MongoDB 是一个 Nosql 数据库',by: '菜鸟教程',url: 'http://www.runoob.com',tags: ['mongodb', 'database', 'NoSQL'],likes: 100
})
>WriteResult({ "nInserted" : 1 })

以上实例中 col 是我们的集合名,如果该集合不在该数据库中, MongoDB 会自动创建该集合并插入文档。

查看已插入文档:

> db.col.find()
>{ "_id" : ObjectId("5ed5a7e356fa4269b4e255fd"), "title" : "MongoDB 教程", "description" : "MongoDB 是一个 Nosql 数据库", "by" : "菜鸟教程", "url" : "http://www.runoob.com", "tags" : [ "mongodb", "database", "NoSQL" ], "likes" : 100 }

我们也可以将数据定义为一个变量,如下所示:

document=({title: 'MongoDB 教程', description: 'MongoDB 是一个 Nosql 数据库',by: '菜鸟教程',url: 'http://www.runoob.com',tags: ['mongodb', 'database', 'NoSQL'],likes: 100
});

执行后显示结果如下:

{"title" : "MongoDB 教程","description" : "MongoDB 是一个 Nosql 数据库","by" : "菜鸟教程","url" : "http://www.runoob.com","tags" : ["mongodb","database","NoSQL"],"likes" : 100
}

执行插入操作:

>db.col.insert(document)
WriteResult({ "nInserted" : 1 })

插入文档你也可以使用 db.col.save(document)命令。如果不指定 _id 字段 save() 方法类似于 insert() 方法。如果指定 _id 字段,则会更新该 _id 的数据。

MongoDB 更新文档

MongoDB 使用 update()save() 方法来更新集合中的文档。接下来让我们详细来看下两个函数的应用及其区别。

update() 方法

语法

update() 方法用于更新已存在的文档。语法格式如下:

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

实例

我们在集合 col 中插入如下数据:

db.col.insert({title: 'MongoDB 教程', description: 'MongoDB 是一个 Nosql 数据库',by: '菜鸟教程',url: 'http://www.runoob.com',tags: ['mongodb', 'database', 'NoSQL'],likes: 100})
WriteResult({ "nInserted" : 1 })

接着我们通过 update() 方法来更新标题(title):

>db.col.update({'title':'MongoDB 教程'},{$set:{'title':'MongoDB'}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.col.find().pretty()
{"_id" : ObjectId("5ed5a7e356fa4269b4e255fd"),"title" : "MongoDB","description" : "MongoDB 是一个 Nosql 数据库","by" : "菜鸟教程","url" : "http://www.runoob.com","tags" : ["mongodb","database","NoSQL"],"likes" : 100
}

可以看到标题(title)由原来的 “MongoDB 教程” 更新为了 “MongoDB”。

以上语句只会修改第一条发现的文档,如果你要修改多条相同的文档,则需要设置 multi 参数为 true。

>db.col.update({'title':'MongoDB 教程'},{$set:{'title':'MongoDB'}},{multi:true})

save() 方法

语法

save() 方法通过传入的文档来替换已有文档,_id 主键存在就更新,不存在就插入。

db.collection.save(<document>,{writeConcern: <document>}
)
  • document : 文档数据。
  • writeConcern :可选,抛出异常的级别。

实例

以下实例中我们替换了 _id 为 5ed5a7e356fa4269b4e255fd的文档数据:

原数据

> db.col.find().pretty()
{"_id" : ObjectId("5ed5a7e356fa4269b4e255fd"),"title" : "MongoDB","description" : "MongoDB 是一个 Nosql 数据库","by" : "菜鸟教程","url" : "http://www.runoob.com","tags" : ["mongodb","database","NoSQL"],"likes" : 100
}

执行更新

db.col.save({"_id" : ObjectId("5ed5a7e356fa4269b4e255fd"),"title" : "MongoDB_Zysheep","description" : "MongoDB 是一个 Nosql 数据库","by" : "Zysheep","url" : "http://www.zysheep.cn","tags" : ["mongodb","NoSQL","zysheep"],"likes" : 120
})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

替换成功后,我们可以通过 find() 命令来查看替换后的数据

db.col.find().pretty()
{"_id" : ObjectId("5ed5a7e356fa4269b4e255fd"),
"title" : "MongoDB_Zysheep",
"description" : "MongoDB 是一个 Nosql 数据库",
"by" : "Zysheep",
"url" : "http://www.zysheep.cn",
"tags" : ["mongodb","NoSQL","zysheep"
],
"likes" : 120
}

MongoDB 删除文档

MongoDB remove()函数是用来移除集合中的数据。MongoDB数据更新可以使用update()函数。在执行remove()函数前先执行find()命令来判断执行的条件是否正确,这是一个比较好的习惯。

语法

db.collection.remove(<query>,<justOne>
)
  • query :(可选)删除的文档的条件。
  • justOne : (可选)如果设为 true 或 1,则只删除一个文档,如果不设置该参数,或使用默认值 false,则删除所有匹配条件的文档。
  • writeConcern :(可选)抛出异常的级别。

实例

# 查询所有数据
> db.col.find()
{ "_id" : ObjectId("5ed5a7e356fa4269b4e255fd"), "title" : "MongoDB_Zysheep", "description" : "MongoDB 是一个 Nosql 数据库", "by" : "Zysheep", "url" : "http://www.zysheep.cn", "tags" : [ "mongodb", "NoSQL", "zysheep" ], "likes" : 120 }
{ "_id" : ObjectId("5ed5a81856fa4269b4e255fe"), "title" : "MongoDB", "description" : "MongoDB 是一个 Nosql 数据库", "by" : "菜鸟教程", "url" : "http://www.runoob.com", "tags" : [ "mongodb", "database", "NoSQL" ], "likes" : 100 }
{ "_id" : ObjectId("5ed5aa2156fa4269b4e25602"), "title" : "MongoDB", "description" : "MongoDB 是一个 Nosql 数据库", "by" : "菜鸟教程", "url" : "http://www.runoob.com", "tags" : [ "mongodb", "database", "NoSQL" ], "likes" : 100 }
# 移除 title 为 'MongoDB' 的文档
>db.col.remove({'title':'MongoDB'})
WriteResult({ "nRemoved" : 2 })
# 再次查询所有文档
>db.col.find()

如果你只想删除第一条找到的记录可以设置 justOne 为 1

>db.COLLECTION_NAME.remove(DELETION_CRITERIA,1)

注意

remove() 方法已经过时了,现在官方推荐使用deleteOne()deleteMany() 方法。

如删除集合下全部文档:

db.COLLECTION_NAME.deleteMany({})

删除 status 等于 A 的全部文档:

db.COLLECTION_NAME.deleteMany({ status : "A" })

删除 status 等于 D 的一个文档:

db.COLLECTION_NAME.deleteOne( { status: "D" } )

MongoDB 查询文档

MongoDB 查询文档使用 find() 方法。

语法

>db.collection.find(query, projection)
  • query :可选,使用查询操作符指定查询条件
  • projection :可选,使用投影操作符指定返回的键。查询时返回文档中所有键值, 只需省略该参数即可(默认省略)。

如果你需要以易读的方式来读取数据,可以使用 pretty() 方法,语法格式如下:

>db.col.find().pretty()

pretty() 方法以格式化的方式来显示所有文档。

> db.col.find().pretty()
{"_id" : ObjectId("56063f17ade2f21f36b03133"),"title" : "MongoDB 教程","description" : "MongoDB 是一个 Nosql 数据库","by" : "菜鸟教程","url" : "http://www.runoob.com","tags" : ["mongodb","database","NoSQL"],"likes" : 100
}

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中条件操作符有:

  • (>) 大于 - $gt
  • (<) 小于 - $lt
  • (>=) 大于等于 - $gte
  • (<= ) 小于等于 - $lte

MongoDB AND 条件

MongoDB 的 find() 方法可以传入多个键(key),每个键(key)以逗号隔开,即常规 SQL 的 AND 条件。

语法格式如下:

>db.col.find({key1:value1, key2:value2}).pretty()

#####实例

以下实例通过 bytitle 键来查询 菜鸟教程MongoDB 教程 的数据

> db.col.find({"by":"菜鸟教程", "title":"MongoDB 教程"}).pretty()
{"_id" : ObjectId("56063f17ade2f21f36b03133"),"title" : "MongoDB 教程","description" : "MongoDB 是一个 Nosql 数据库","by" : "菜鸟教程","url" : "http://www.runoob.com","tags" : ["mongodb","database","NoSQL"],"likes" : 100
}

以上实例中类似于 WHERE 语句:WHERE by=‘菜鸟教程’ AND title=‘MongoDB 教程’

MongoDB OR 条件

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

>db.col.find({$or: [{key1: value1}, {key2:value2}]}
).pretty()
实例

以下实例中,我们演示了查询键 by 值为 菜鸟教程 或键 title 值为 MongoDB 教程 的文档。

>db.col.find({$or:[{"by":"菜鸟教程"},{"title": "MongoDB 教程"}]}).pretty()
{"_id" : ObjectId("56063f17ade2f21f36b03133"),"title" : "MongoDB 教程","description" : "MongoDB 是一个 Nosql 数据库","by" : "菜鸟教程","url" : "http://www.runoob.com","tags" : ["mongodb","database","NoSQL"],"likes" : 100
}

AND 和 OR 联合使用

以下实例演示了 AND 和 OR 联合使用,类似常规 SQL 语句为: ‘where likes>50 AND (by = ‘菜鸟教程’ OR title = ‘MongoDB 教程’)’

>db.col.find({"likes": {$gt:50}, $or: [{"by": "菜鸟教程"},{"title": "MongoDB 教程"}]}).pretty()
{"_id" : ObjectId("56063f17ade2f21f36b03133"),"title" : "MongoDB 教程","description" : "MongoDB 是一个 Nosql 数据库","by" : "菜鸟教程","url" : "http://www.runoob.com","tags" : ["mongodb","database","NoSQL"],"likes" : 100
}

docker 部署 mongodb

拉取镜像

docker pull mongo

可以查看镜像是否下载成功

docker images | grep mongo

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Mf1YWpCd-1619779608515)(C:\Users\L15096000421\AppData\Roaming\Typora\typora-user-images\1591003616968.png)]

docker 安装 mongodb

docker run --name mongodb -v /data/mongodb0:/data/db -p 27017:27017 -d mongo

执行上述命令之后, 一个挂载了 mongo镜像的容器就开始运行了

  • --name 设置了容器的名字
  • -v 设置了路径的映射, 将本地路径映射到容器中. 此处, 路径可以自定义
  • -p 设置了端口的映射, 将容器的27017(右侧) 映射到了本地的27017(右侧)

进入容器.

docker exec -it mongodb bash

上述命令的意思如下:使用交互的形式, 在 名字为 mongodb 的容器中实行 bash这个命令

mongodb的使用

用户的创建

输入以下命令进入 mongo

创建用户

 # 进入 admin 的数据库> use admin
switched to db admin
# 创建管理员用户
> db.createUser(
...    {...      user: "admin",
...      pwd: "123456",
...      roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
...    }
...  )
Successfully added user: {"user" : "admin","roles" : [{"role" : "userAdminAnyDatabase","db" : "admin"}]
}# 创建有可读写权限的用户. 对于一个特定的数据库, 比如'demo'
>  db.createUser({...      user: 'test',
...      pwd: '123456',
...      roles: [{role: "read", db: "demo"}]
...  })
Successfully added user: {"user" : "test","roles" : [{"role" : "read","db" : "demo"}]
}

数据库的建立

use demo;

mongo 是否正常启动的校验

先写入一条数据

db.info.save({name: 'test', age: '22'})

查看写入的数据

db.info.find();

结果如下

# 数据库的建立
> use demo;
switched to db demo
# 先写入一条数据
> db.info.save({name: 'test', age: '22'})
WriteResult({ "nInserted" : 1 })
#
> db.info.find();
{ "_id" : ObjectId("5ed4cc9c3f1db5d1d0e02f01"), "name" : "test", "age" : "22" }

远程连接的开启

mongodb 的容器当中

#更新源
apt-get update
# 安装 vim
apt-get install vim
# 修改 mongo 配置文件
vim /etc/mongod.conf.orig

将其中的bindIp: 127.0.0.1注释掉# bindIp: 127.0.0.1或者改成bindIp: 0.0.0.0即可开启远程连接

基于MongoTemplate 开发CRUD

1、引入springboot mongo依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

2、mongo的IP和端口

在resources下的application.yml中加入如下内容,端口默认:27017

spring:data:mongodb:uri: mongodb://172.16.0.192/test

3、使用mongoTemplate

User

/*** @version v1.0.0* @ProjectName: springboot-learning-examples* @ClassName: User* @Author: 三月三*/
@Data
@Document("User")
public class User {@Idprivate String id;private String name;private Integer age;private String email;private String createDate;
}

常用方法

mongoTemplate.findAll(User.class): 查询User文档的全部数据
mongoTemplate.findById(<id>, User.class): 查询User文档id为id的数据
mongoTemplate.find(query, User.class);: 根据query内的查询条件查询
mongoTemplate.upsert(query, update, User.class): 修改
mongoTemplate.remove(query, User.class): 删除
mongoTemplate.insert(User): 新增Query对象
1、创建一个query对象(用来封装所有条件对象),再创建一个criteria对象(用来构建条件)
2、 精准条件:criteria.and(“key”).is(“条件”)
模糊条件:criteria.and(“key”).regex(“条件”)
3、封装条件:query.addCriteria(criteria)
4、大于(创建新的criteria):Criteria gt = Criteria.where(“key”).gt(“条件”)
小于(创建新的criteria):Criteria lt = Criteria.where(“key”).lt(“条件”)
5、Query.addCriteria(new Criteria().andOperator(gt,lt));
6、一个query中只能有一个andOperator()。其参数也可以是Criteria数组。
7、排序 :query.with(new Sort(Sort.Direction.ASC, "age"). and(new Sort(Sort.Direction.DESC, "date")))

测试

@SpringBootTest
class DemomogoApplicationTests {@Autowiredprivate MongoTemplate mongoTemplate;//添加@Testpublic void createUser() {User user = new User();user.setAge(20);user.setName("zysheep");user.setEmail("zysheep@126.com");User user1 = mongoTemplate.insert(user);System.out.println(user1);}//查询所有@Testpublic void findUser() {List<User> userList = mongoTemplate.findAll(User.class);System.out.println(userList);}//根据id查询@Testpublic void getById() {User user = mongoTemplate.findById("5ffbfa2ac290f356edf9b5aa", User.class);System.out.println(user);}//条件查询@Testpublic void findUserList() {Query query = new Query(Criteria.where("name").is("zysheep").and("age").is(20));List<User> userList = mongoTemplate.find(query, User.class);System.out.println(userList);}//模糊查询@Testpublic void findUsersLikeName() {String name = "eep";String regex = String.format("%s%s%s", "^.*", name, ".*$");Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);Query query = new Query(Criteria.where("name").regex(pattern));List<User> userList = mongoTemplate.find(query, User.class);System.out.println(userList);}//分页查询@Testpublic void findUsersPage() {String name = "est";int pageNo = 1;int pageSize = 10;Query query = new Query();String regex = String.format("%s%s%s", "^.*", name, ".*$");Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);query.addCriteria(Criteria.where("name").regex(pattern));int totalCount = (int) mongoTemplate.count(query, User.class);List<User> userList = mongoTemplate.find(query.skip((pageNo - 1) * pageSize).limit(pageSize), User.class);Map<String, Object> pageMap = new HashMap<>();pageMap.put("list", userList);pageMap.put("totalCount",totalCount);System.out.println(pageMap);}//修改@Testpublic void updateUser() {User user = mongoTemplate.findById("5ffbfa2ac290f356edf9b5aa", User.class);user.setName("test_1");user.setAge(25);user.setEmail("493220990@qq.com");Query query = new Query(Criteria.where("_id").is(user.getId()));Update update = new Update();update.set("name", user.getName());update.set("age", user.getAge());update.set("email", user.getEmail());UpdateResult result = mongoTemplate.upsert(query, update, User.class);long count = result.getModifiedCount();System.out.println(count);}//删除操作@Testpublic void delete() {Query query =
new Query(Criteria.where("_id").is("5ffbfa2ac290f356edf9b5aa"));DeleteResult result = mongoTemplate.remove(query, User.class);long count = result.getDeletedCount();System.out.println(count);}
}

为了方便测试,封装了MongodbUtils

package cn.zysheep.springboot.utils;import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import javax.annotation.PostConstruct;import cn.zysheep.springboot.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.GroupOperation;
import org.springframework.data.mongodb.core.aggregation.MatchOperation;
import org.springframework.data.mongodb.core.index.Index;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;/*** @version v1.0.0* @ProjectName: springboot-learning-examples* @ClassName: MongodbUtils* @Author: 三月三*/@Component
public class MongodbUtils {public static MongodbUtils mongodbUtil;@PostConstructpublic void init() {mongodbUtil = this;mongodbUtil.mongoTemplate = this.mongoTemplate;}@Autowiredprivate MongoTemplate mongoTemplate;/*** 保存对象List到指定集合中* <p>* 也可以在实体类上使用@Document(collection=“集合名称”)指定集合名称,未指定则默认实体类的类名为集合名称** @param entiys*/public static void saveAll(String collName, List<?> entiys) {for (Object entiy : entiys) {saveData(collName, entiy);}}/*** 保存单个对象到指定集合中** @param collName 集合名称* @param entiy    实体名称*/public static void saveOne(String collName, Object entiy) {saveData(collName, entiy);}/*** 根据id倒序查询 集合中的数据** @param entiy     数据实体* @param collName  集合名称* @param direction 倒序/正序 Direction.DESC/ASC* @param*/public static Object findSortById(Class<?> entiy, String collName, Sort.Direction direction) {Query query = new Query().with(Sort.by(direction, "id"));return mongodbUtil.mongoTemplate.find(query, entiy, collName);}/*** 查询返回指定字段** @param fields   需要返回的指定字段* @param clazz    数据实体类class* @param collName 集合名称* @param map      Map<查询条件key,查询条件value>*                 <p>*                 返回字段的时候id默认为返回,不返回id则field设置  fieldObj.put("id",false)* @return*/public static Object findDesignField(List<String> fields, Map<String, Object> map, Class<?> clazz, String collName, boolean returnId) {Criteria criteria = null;if (map.containsKey(null)) {return "查询条件key不能为Null~";}for (String key : map.keySet()) {criteria = Criteria.where(key).is(map.get(key));}Query query = new Query(criteria);for (String field : fields) {query.fields().include(field);}if (!returnId) {query.fields().exclude("id");}return mongodbUtil.mongoTemplate.find(query, clazz, collName);}/*** 查询指定集合中的所有数据** @param entiy    数据实体类* @param collName 集合名称*/public static Object findAll(Class<?> entiy, String collName) {return mongodbUtil.mongoTemplate.findAll(entiy, collName);}/*** 模糊查询 根据 key 可以到 collName 中进行模糊查询 并排序** @param param     匹配的参数* @param collName  集合名称* @param direction Direction.desc /asc 倒序/正序* @param sortField 排序字段* @return*/public static Object findLikeByParam(String param, String collName, String sortField, Sort.Direction direction,Class<?> entiy) {Pattern pattern = Pattern.compile("^.*" + param + ".*$", Pattern.CASE_INSENSITIVE);Query query = new Query(Criteria.where("name").regex(pattern)).with(Sort.by(direction, sortField));return mongodbUtil.mongoTemplate.find(query, entiy, collName);}/*** 向指定集合设置索引** @param collName  集合名称* @param indexName 索引名称* @param map       map.put("添加索引的字段",Direction.ASC/DESC)*/public static void createIndex(String collName, String indexName, Map<String, Sort.Direction> map) throws Exception {if (map.containsKey(null)) {throw new Exception("添加索引的字段不能为null");}Index index = new Index().named(indexName);for (String key : map.keySet()) {index.on(key, map.get(key));}mongodbUtil.mongoTemplate.indexOps(collName).ensureIndex(index);}/*** 获取指定集合中的索引信息** @param collName 集合名称* @return*/public static Object getIndexInfo(String collName) {return mongodbUtil.mongoTemplate.indexOps(collName).getIndexInfo();}/*** 根据索引名称删除索引** @param indexName 索引名称* @param collName  集合名称*/public static void removeIndexByName(String collName, String indexName) {mongodbUtil.mongoTemplate.indexOps(collName).dropIndex(indexName);}/*** 删除指定集合中得所有索引** @param collName 集合名称*/public static void removeIndexByName(String collName) {mongodbUtil.mongoTemplate.indexOps(collName).dropAllIndexes();}/*** 根据指定key 和value到指定collName集合中删除数据** @param key* @param value* @param collName*/public static void removeAllByParam(String key, String value, String collName) {Criteria criteria = Criteria.where(key).is(value);Query query = Query.query(criteria);mongodbUtil.mongoTemplate.remove(query, collName);}/*** 根据指定条件查询 并排序** @param obj      数据对象* @param map      Map<"查询条件key",查询条件值> map* @param collName 集合名称* @return*/public static List<? extends Object> findSortByParam(Object obj, String collName, Map<String, Object> map, String sortField, Sort.Direction direction) {if (map.containsKey(null)) {return new ArrayList<>();}Criteria criteria = null;criteria = getCriteria(criteria, map);if (criteria == null) {return new ArrayList<>();}Query query = Query.query(criteria).with(Sort.by(direction, sortField));return mongodbUtil.mongoTemplate.find(query, obj.getClass(), collName);}/*** 范围查询* <p>* 查询大于等于begin  小于等于end范围内条件匹配得数据并排序** @param obj           数据对象* @param collName      集合名称* @param map           Map<"查询条件key",查询条件值> map* @param sortField     排序字段* @param direction     排序方式  Direction.asc   / Direction.desc* @param rangeCriteria 示例: lt小于  lte 小于等于  gt大于  gte大于等于 eq等于 ne不等于*                      <p>*                      Criteria rangeCriteria=Criteria.where("createDate").gte(begin).lte(end));*                      <p>*                      createDate:数据库中的时间字段,gegin:起始时间  end:结束时间* @return*/public static List<? extends Object> findRangeByParam(Object obj, String collName, Map<String, Object> map,String sortField, Sort.Direction direction, Criteria rangeCriteria) {if (map.containsKey(null)) {return new ArrayList<>();}Criteria criteria = null;criteria = getCriteria(criteria, map);if (criteria == null) {return new ArrayList<>();}Query query = new Query().addCriteria(rangeCriteria).addCriteria(criteria).with(Sort.by(direction, sortField));return mongodbUtil.mongoTemplate.find(query, obj.getClass(), collName);}/*** 根据指定key value到指定集合中查询匹配得数量** @param collName* @param key* @param value* @return*/public static long count(String collName, String key, String value) {Query query = Query.query(Criteria.where(key).is(value));return mongodbUtil.mongoTemplate.count(query, "goods");}/*** 在指定范围内查询匹配条件的数量** @param clazz         数据实体类* @param collName      集合名称* @param map           查询条件map* @param rangeCriteria 范围条件  Criteria rangeCriteria= Criteria.where("数据库字段").gt/gte(起始范围).lt/lte(结束范围)* @return*/public static Long countRangeCondition(Class<?> clazz, String collName, Criteria rangeCriteria, Map<String, Object> map) {Criteria criteria = null;if (map.containsKey(null)) {return null;}for (String key : map.keySet()) {criteria = Criteria.where(key).is(map.get(key));}Query query = new Query();if (criteria != null) {query.addCriteria(criteria);}query.addCriteria(rangeCriteria);return mongodbUtil.mongoTemplate.count(query, clazz, collName);}/*** 指定集合 根据条件查询出符合的第一条数据** @param entiy          数据对象* @param map            条件map  Map<条件key,条件value> map* @param collectionName 集合名* @return*/public static Object findSortFirst(Class<?> entiy, Map<String, Object> map, String collectionName, String field, Sort.Direction direction) {if (map.containsKey(null)) {return "查询条件不能为null~";}Criteria criteria = null;criteria = getCriteria(criteria, map);Query query = Query.query(criteria).with(Sort.by(direction, field));return mongodbUtil.mongoTemplate.findOne(query, entiy, collectionName);}/*** 指定集合 修改数据,且修改所找到的所有数据** @param accordingKey   修改条件 key* @param accordingValue 修改条件 value* @param map            Map<修改内容 key数组,修改内容 value数组>* @param collName       集合名* @param type           修改操作类型  1:修改第一条数据  0:修改所有匹配得数据*/public static void updateMulti(String accordingKey, Object accordingValue, Map<String, Object> map,String collName, Integer type) {if (map.containsKey(null)) {return;}Criteria criteria = Criteria.where(accordingKey).is(accordingValue);Query query = Query.query(criteria);Update update = new Update();for (String key : map.keySet()) {update.set(key, map.get(key));}if (type == 1) {mongodbUtil.mongoTemplate.updateFirst(query, update, collName);} else {mongodbUtil.mongoTemplate.updateMulti(query, update, collName);}}/*** 对某字段做sum求和** @param clazz         数据实体类* @param map           Map<查询条件key,查询条件value> map* @param collName      集合名称* @param sumField      求和字段* @param rangeCriteria 范围条件* @return Criteria rangeCriteria = Criteria.where(字段).gt(起始范围).lt(结束范围)*/public static Object findSum(Class<?> clazz, Map<String, Object> map, String collName, String sumField, Criteria rangeCriteria) {if (map.containsKey(null)) {return "查询条件key不能为Null";}Criteria criteria = null;MatchOperation match = null;for (String key : map.keySet()) {criteria = Criteria.where(key).is(map.get(key));}if (criteria != null) {match = Aggregation.match(criteria);}GroupOperation count = Aggregation.group().sum(sumField).as(sumField);return mongodbUtil.mongoTemplate.aggregate(Aggregation.newAggregation(match, count), collName, clazz).getMappedResults();}/*** 分页查询** @param entiy     数据实体类* @param collName  集合名称* @param map       Map<"查询条件key",查询条件值> map 若 keys/values 为null,则查询集合中所有数据* @param pageNo    当前页* @param pageSize  当前页数据条数* @param direction Direction.Desc/ASC 排序方式* @param sortField 排序字段* @return*/public static PageModel findSortPageCondition(Class<?> entiy, String collName, Map<String, Object> map,int pageNo, int pageSize, Sort.Direction direction, String sortField) {Criteria criteria = getCriteria(new Criteria(), map);long count;if (criteria == null) {count = mongodbUtil.mongoTemplate.count(new Query(), entiy, collName);} else {count = mongodbUtil.mongoTemplate.count(new Query(criteria), entiy, collName);}int pages = (int) Math.ceil((double) count / (double) pageSize);if (pageNo <= 0 || pageNo > pages) {pageNo = 1;}int skip = pageSize * (pageNo - 1);Query query = new Query().skip(skip).limit(pageSize);query.with(Sort.by(direction, sortField));if (criteria != null) {query.addCriteria(criteria);}List<?> list = mongodbUtil.mongoTemplate.find(query, entiy, collName);PageModel pageModel = new PageModel();pageModel.setPageNo(pageNo);pageModel.setPagesize(pageSize);pageModel.setTotal(count);pageModel.setPages(pages);pageModel.setList(list);return pageModel;}private static void saveData(String collName, Object entiy) {if (StringUtils.isEmpty(collName)) {mongodbUtil.mongoTemplate.save(entiy);} else {mongodbUtil.mongoTemplate.save(entiy, collName);}}private static Criteria getCriteria(Criteria criteria, Map<String, Object> map) {if (map == null) {return null;}int i = 0;for (String key : map.keySet()) {if (i == 0) {criteria = Criteria.where(key).is(map.get(key));i++;} else {criteria.and(key).is(map.get(key));}}return criteria;}
}
package cn.zysheep.springboot.utils;import java.io.Serializable;
import java.util.List;/*** @version v1.0.0* @ProjectName: springboot-learning-examples* @ClassName: PageModel* @Author: 三月三*/
public class PageModel implements Serializable {private static final long serialVersionUID = 1L;/*** 当前页*/private Integer pageNo = 1;/*** 当前页条数*/private Integer pagesize = 10;/*** 总共的条数*/private Long total;/*** 总共的页数*/private Integer pages;/*** 实体类集合*/private List<?> list;public Integer getPageNo() {return pageNo;}public void setPageNo(Integer pageNo) {this.pageNo = pageNo;}public Integer getPagesize() {return pagesize;}public void setPagesize(Integer pagesize) {this.pagesize = pagesize;}public Long getTotal() {return total;}/*** 总数由0开始计数* @param total*/public void setTotal(Long total) {this.total = total + 1;}public Integer getPages() {return pages;}public void setPages(Integer pages) {this.pages = pages;}public List<?> getList() {return list;}public void setList(List<?> list) {this.list = list;}public PageModel(Integer pageNo, Integer pagesize, Long total, Integer pages, List<?> list) {this.pageNo = pageNo;this.pagesize = pagesize;this.total = total;this.pages = pages;this.list = list;}public PageModel() {}@Overridepublic String toString() {return "PageModel{" +"pageNo=" + pageNo +", pagesize=" + pagesize +", total=" + total +", pages=" + pages +", list=" + list +'}';}
}

测试

package cn.zysheep.springboot;import cn.zysheep.springboot.entity.User;
import cn.zysheep.springboot.repository.UserRepository;
import cn.zysheep.springboot.utils.MongodbUtils;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import java.util.ArrayList;
import java.util.List;@SpringBootTest
class Springboot06DataMongodbApplicationTests {@Autowiredprivate UserRepository userRepository;@Autowiredprivate MongodbUtils mongodbUtils;// 测试添加文档@Testpublic void testSaveUser() throws Exception {User user=new User();user.setId(1l);user.setUserName("明世隐");user.setPassWord("123456");userRepository.saveUser(user);}// 测试根据名字查询文档@Testpublic void findUserByUserName(){User user= userRepository.findUserByUserName("明世隐");System.out.println("user is "+user);}// 测试修改文档@Testpublic void updateUser(){User user=new User();user.setId(2l);user.setUserName("韩信");user.setPassWord("123456789");userRepository.updateUser(user);}// 测试删除@Testpublic void deleteUserById(){userRepository.deleteUserById(1l);}@Testvoid test1(){List<User> user = (List<User>)MongodbUtils.findAll(User.class, "user");user.forEach(System.out::println);}@Testvoid test2(){MongodbUtils.saveOne("user",new User(5L,"干将莫邪","123123"));}@Testvoid test3(){ArrayList<User> list = new ArrayList<>();list.add(new User(6L,"荆轲","123123"));list.add(new User(7L,"赵云","12312"));list.add(new User(8L,"公孙离","asdfasdf"));list.add(new User(9L,"伽罗","hdfgsdfg"));MongodbUtils.saveAll("user",list);}}

基于MongoRepository开发CRUD

Spring Data提供了对mongodb数据访问的支持,我们只需要继承MongoRepository类,按照Spring Data规范就可以了
SpringData 方法定义规范

  1. 不是随便声明的,而需要符合一定的规范
  2. 查询方法以find | read | get开头
  3. 涉及条件查询时,条件的属性用条件关键字连接
  4. 要注意的是:条件属性首字母需要大写
  5. 支持属性的级联查询,但若当前类有符合条件的属性则优先使用,而不使用级联属性,若需要使用级联属性,则属性之间使用_强制进行连接

添加Repository类

UserRepository

@Repository
public interface UserRepository extends MongoRepository<User, String> {}

测试

@SpringBootTest
class DemomogoApplicationTests1 {@Autowiredprivate UserRepository userRepository;//添加@Testpublic void createUser() {User user = new User();user.setAge(20);user.setName("张三");user.setEmail("3332200@qq.com");User user1 = userRepository.save(user);}//查询所有@Testpublic void findUser() {List<User> userList = userRepository.findAll();System.out.println(userList);}//id查询@Testpublic void getById() {User user = userRepository.findById("5ffbfe8197f24a07007bd6ce").get();System.out.println(user);}//条件查询@Testpublic void findUserList() {User user = new User();user.setName("张三");user.setAge(20);Example<User> userExample = Example.of(user);List<User> userList = userRepository.findAll(userExample);System.out.println(userList);}//模糊查询@Testpublic void findUsersLikeName() {//创建匹配器,即如何使用查询条件ExampleMatcher matcher = ExampleMatcher.matching() //构建对象.withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING) //改变默认字符串匹配方式:模糊查询.withIgnoreCase(true); //改变默认大小写忽略方式:忽略大小写User user = new User();user.setName("三");Example<User> userExample = Example.of(user, matcher);List<User> userList = userRepository.findAll(userExample);System.out.println(userList);}//分页查询@Testpublic void findUsersPage() {Sort sort = Sort.by(Sort.Direction.DESC, "age");
//0为第一页Pageable pageable = PageRequest.of(0, 10, sort);
//创建匹配器,即如何使用查询条件ExampleMatcher matcher = ExampleMatcher.matching() //构建对象.withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING) //改变默认字符串匹配方式:模糊查询.withIgnoreCase(true); //改变默认大小写忽略方式:忽略大小写User user = new User();user.setName("三");Example<User> userExample = Example.of(user, matcher);
//创建实例Example<User> example = Example.of(user, matcher);Page<User> pages = userRepository.findAll(example, pageable);System.out.println(pages);}//修改@Testpublic void updateUser() {User user = userRepository.findById("5ffbfe8197f24a07007bd6ce").get();user.setName("张三_1");user.setAge(25);user.setEmail("883220990@qq.com");User save = userRepository.save(user);System.out.println(save);}//删除@Testpublic void delete() {userRepository.deleteById("5ffbfe8197f24a07007bd6ce");}
}

多数据源 MongoDB 的使用

pom

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

yml

spring:data:mongodb:host1: 172.16.0.192host2: 172.16.0.192dbName:primaryDb: primarysecondaryDb: secondary

MongoConfig

package cn.zysheep.springboot.config;import com.mongodb.MongoClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;/*** @version v1.0.0* @ProjectName: springboot-learning-examples* @ClassName: MongoConfig* @Author: 三月三*/
@Configuration
public class MongoConfig {//读取配置文件里的值,部署后IP或者数据库名变化,不需重新打包@Value("${spring.data.mongodb.host1}")private String mongohost1;@Value("${spring.data.mongodb.host2}")private String mongohost2;@Value("${spring.data.dbName.primaryDb}")private String primaryDb;@Value("${spring.data.dbName.secondaryDb}")private String secondaryDb;@Bean@Primarypublic MongoClient mongoClient() {return new MongoClient(mongohost1);}@Beanpublic  MongoClient mongoClient2() {return new MongoClient(mongohost2);}@Bean@Primarypublic   MongoTemplate primaryMongoTemplate() {return new MongoTemplate(mongoClient(), primaryDb);}@Beanpublic   MongoTemplate secondaryMongoTemplate() {return  new MongoTemplate(new SimpleMongoDbFactory(mongoClient(), secondaryDb));}
}

Person

package cn.zysheep.springboot.entity;import lombok.Data;
import org.springframework.stereotype.Component;/*** @version v1.0.0* @ProjectName: springboot-learning-examples* @ClassName: Person* @Author: 三月三*/@Component
@Data
public class Person {private String id;private String name;private int age;public Person() {}public Person(String id, String name, int age) {this.id = id;this.name = name;this.age = age;}@Overridepublic String toString() {return "Person{" +"id='" + id + '\'' +", name='" + name + '\'' +", age=" + age +'}';}
}

测试

package cn.zysheep.springboot;
import cn.zysheep.springboot.entity.Person;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import javax.annotation.Resource;@SpringBootTest
class Springboot06DataMultiMongodb22XApplicationTests {//这里用Resource,没有用Autoware@Resourceprivate MongoTemplate primaryMongoTemplate;@Resourceprivate MongoTemplate secondaryMongoTemplate;//右键运行,看看两个库是否同时插入了数据@Testpublic void insert(){Person p=new Person("001","tom",88);primaryMongoTemplate.insert(p);Person p2=new Person("N0012","zhangsan",14);secondaryMongoTemplate.insert(p2);}@Testpublic void queryon(){Person qp = primaryMongoTemplate.findOne(new Query(new Criteria("name").is("tom")), Person.class);System.out.println(qp);}@Testpublic void getOne(){//不指定数据集,根据实体类的类名获取数据集。 这里Person也会被当作collectionNamePerson zz = primaryMongoTemplate.findOne(new Query(new Criteria("name").is("tom")), Person.class);//指定数据集   同一个数据库下,建了一个user集合,跟person结构相同,这时就要指定了Person one = primaryMongoTemplate.findOne(new Query(new Criteria("name").is("tom")), Person.class,"primary");System.out.println(one);}
}

【SpringBoot高级篇】SpringBoot集成MongDB数据库相关推荐

  1. 【SpringBoot高级篇】SpringBoot集成Elasticsearch搜索引擎

    [SpringBoot高级篇]SpringBoot集成Elasticsearch搜索引擎 1. 什么是Elasticsearch? 2. 安装并运行Elasticsearch 2.1 拉取镜像 2.2 ...

  2. 【SpringBoot高级篇】SpringBoot集成jasypt 配置脱敏和数据脱敏

    [SpringBoot高级篇]SpringBoot集成jasypt数据脱敏 配置脱敏 使用场景 配置脱敏实践 数据脱敏 pom yml EncryptMethod EncryptField Encry ...

  3. 【SpringBoot高级篇】springboot实现上传docdocx文件格式转html在线预览v2.0

    [SpringBoot高级篇]springboot实现上传doc&docx文件格式转html在线预览v2.0 pom 上传路径工具类 SpringMvc虚拟路径映射 doc转html工具类 d ...

  4. 【SpringBoot高级】SpringBoot整合篇

    SpringBoot整合篇

  5. SpringBoot高级篇JdbcTemplate之数据查询上篇

    前面一篇介绍如何使用JdbcTemplate实现插入数据,接下来进入实际业务中,最常见的查询篇.由于查询的姿势实在太多,对内容进行了拆分,本篇主要介绍几个基本的使用姿势 queryForMap que ...

  6. SpringBoot高级篇MongoDB之修改基本使用姿势

    原文: 190218-SpringBoot高级篇MongoDB之修改基本使用姿势 本篇依然是MongoDB curd中的一篇,主要介绍document的更新,主要内容如下 常见类型成员的修改 数组类型 ...

  7. springboot高级篇及springboot1.5转springboot2.17所遇到的坑

    SpringBoot的高级教程 一.SpringBoot缓存 缓存的场景 临时性数据存储[校验码] 避免频繁因为相同的内容查询数据库[查询的信息] 1.JSR107缓存规范 用的比较少 Java Ca ...

  8. Java高级篇-----Springboot框架

    目录 1.什么是Springboot 2.Springboot框架的特点 3.创建Springboot工程 3.1.准备条件 3.2. 创建springboot的方式有两种 3.2.1. 使用idea ...

  9. springboot高级篇(认证,授权)

    认证,授权 1,项目 1.1登陆 1.2,注销 1.3,认证授权 1.4,记住我功能 认证:证明你是谁,携带用户名和密码.系统查验是你这个人的过程. 授权:认证以后你能干什么,访问资源的权限 1,项目 ...

最新文章

  1. C#--多线程--2
  2. 缺少物联网杀手级应用的运营商,到底该怎么办?
  3. spring bean作用域_Srping中Bean的三种装配方式:大魏Java记10
  4. 0、elasticsearch前言
  5. javascript小游戏_javaScript小游戏——网页版别踩白块
  6. java共同方法_java-现有公共方法的NoSuchMethodError
  7. android长按非控件处,Android常用之Butterknife使用详解
  8. Cookie 版购物车
  9. 网易云基于 Kubernetes 的深度定制化实践
  10. mysql拼装字段_Mysql 实现字段拼接的三个函数
  11. JS网页恶搞代码,不断弹出、关不掉的对话框
  12. 对话罗永浩:手机行业唯一的聪明人死了,我胜算很大
  13. NO.3 微信第三方平台代创建小程序审核发布以及小程序信息(头像,名称,简介)修改 以及微信错误码 返回信息
  14. 基于 WebRTC 创建一款多人联机游戏
  15. 写switch case语句不加break会怎样。
  16. 大班线描机器人_大班线描画-有趣的巨人
  17. 音视频播放疑难杂症分析和解决思路
  18. C++调用Python(混合编程)函数整理总结
  19. 关于for循环中三个语句的执行顺序
  20. (转)FFmpeg 基本用法

热门文章

  1. PHP MySQL 插入数据
  2. python操作mysql数据库用到的fetchone()函数和fetchall()函数
  3. 谈PHP发展前景和就业解析 -兄弟连IT教育
  4. Linux学习之计算机基础理论
  5. 台式计算机无法访问网络,完美:台式计算机的解决方案无法访问Internet,但手机可以连接到wifi无线网络...
  6. SpringBoot系列之Hikari连接池
  7. 深坑之Webview,解决H5调用android相机拍照和录像
  8. 2021年高压电工考试题及高压电工考试题库
  9. 使用SearchGuard对ElasticSearch进行权限访问控制
  10. orgChart实现竖向排列组织图(js实现组织机构图)