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

MongoDB是什么 ?

  • MongoDB 是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统。
  • 在高负载的情况下,添加更多的节点,可以保证服务器性能。
  • MongoDB 旨在为WEB应用提供可扩展的高性能数据存储解决方案。
  • MongoDB 将数据存储为一个文档,数据结构由键值(key=>value)对组成。MongoDB 文档类似于 JSON 对象。字段值可以包含其他文档,数组及文档数组。
{
      user: "admin",    --->key=>value
      pwd: "123456",	--->key=>value
      roles: [ { 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术语/概念解释/说明
databasedatabase数据库
tablecollection数据库表/集合
rowdocument数据记录行/文档
columnfield数据字段/域
indexindex索引
table joins表连接,MongoDB不支持
primary keyprimary 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 对应的术语:

RDBMSMongoDB
数据库数据库
表格集合
文档
字段
表联合嵌入文档
主键主键 (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 {
 @Id
 private 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 {

    @Autowired
    private MongoTemplate mongoTemplate;

    //添加
    @Test
    public 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);
    }

    //查询所有
    @Test
    public void findUser() {
        List<User> userList = mongoTemplate.findAll(User.class);
        System.out.println(userList);
    }

    //根据id查询
    @Test
    public void getById() {
        User user = mongoTemplate.findById("5ffbfa2ac290f356edf9b5aa", User.class);
        System.out.println(user);
    }

    //条件查询
    @Test
    public 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);
    }

    //模糊查询
    @Test
    public 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);
    }

    //分页查询
    @Test
    public 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);
    }

    //修改
    @Test
    public 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);
    }

    //删除操作
    @Test
    public 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;

    @PostConstruct
    public void init() {
        mongodbUtil = this;
        mongodbUtil.mongoTemplate = this.mongoTemplate;
    }

    @Autowired
    private 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() {
    }

    @Override
    public 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 {

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private MongodbUtils mongodbUtils;

    // 测试添加文档
    @Test
    public void testSaveUser() throws Exception {
        User user=new User();
        user.setId(1l);
        user.setUserName("明世隐");
        user.setPassWord("123456");
        userRepository.saveUser(user);
    }


    // 测试根据名字查询文档
    @Test
    public void findUserByUserName(){
        User user= userRepository.findUserByUserName("明世隐");
        System.out.println("user is "+user);
    }

    // 测试修改文档
    @Test
    public void updateUser(){
        User user=new User();
        user.setId(2l);
        user.setUserName("韩信");
        user.setPassWord("123456789");
        userRepository.updateUser(user);
    }

    // 测试删除
    @Test
    public void deleteUserById(){
        userRepository.deleteUserById(1l);
    }


    @Test
    void test1(){
        List<User> user = (List<User>)MongodbUtils.findAll(User.class, "user");
        user.forEach(System.out::println);
    }


    @Test
    void test2(){
        MongodbUtils.saveOne("user",new User(5L,"干将莫邪","123123"));
    }


    @Test
    void 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 {

    @Autowired
    private UserRepository userRepository;

    //添加
    @Test
    public void createUser() {
        User user = new User();
        user.setAge(20);
        user.setName("张三");
        user.setEmail("3332200@qq.com");
        User user1 = userRepository.save(user);
    }

    //查询所有
    @Test
    public void findUser() {
        List<User> userList = userRepository.findAll();
        System.out.println(userList);
    }

    //id查询
    @Test
    public void getById() {
        User user = userRepository.findById("5ffbfe8197f24a07007bd6ce").get();
        System.out.println(user);
    }

    //条件查询
    @Test
    public 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);
    }

    //模糊查询
    @Test
    public 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);
    }

    //分页查询
    @Test
    public 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);
    }

    //修改
    @Test
    public 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);
    }

    //删除
    @Test
    public 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.192
      host2: 172.16.0.192
    dbName:
      primaryDb: primary
      secondaryDb: 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
    @Primary
    public MongoClient mongoClient() {
        return new MongoClient(mongohost1);
    }
    @Bean
    public  MongoClient mongoClient2() {
        return new MongoClient(mongohost2);
    }

    @Bean
    @Primary
    public   MongoTemplate primaryMongoTemplate() {
        return new MongoTemplate(mongoClient(), primaryDb);
    }
    @Bean
    public   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;
    }
    @Override
    public 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
    @Resource
    private MongoTemplate primaryMongoTemplate;
    @Resource
    private MongoTemplate secondaryMongoTemplate;

   //右键运行,看看两个库是否同时插入了数据
    @Test
    public void insert(){
        Person p=new Person("001","tom",88);
        primaryMongoTemplate.insert(p);
        Person p2=new Person("N0012","zhangsan",14);
        secondaryMongoTemplate.insert(p2);
    }

    @Test
    public void queryon(){
        Person qp = primaryMongoTemplate.findOne(new Query(new Criteria("name").is("tom")), Person.class);
        System.out.println(qp);
    }

    @Test
    public void getOne(){
        //不指定数据集,根据实体类的类名获取数据集。 这里Person也会被当作collectionName
        Person 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);
    }
}
  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

李熠漾

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值