MongoDB概述
结构化数据库
结构化数据库是一种使用结构化查询语言(SQL)进行管理和操作的数据库,它们的数据存储方式是基于表格和列的。结构化数据库要求数据预先定义数据模式和结构,然后才能存储和查询数据。结构化数据库通常具有以下特点:
-
数据预定义:在存储数据之前,需要先定义数据结构和数据类型。这些定义通常存储在数据库的元数据中,并用于确保数据库中的数据一致性和完整性。
-
数据之间的关系:结构化数据库使用表格来存储数据,并且通常有多个表格之间的关系。通过在表格之间建立外键关系,可以在查询时轻松地检索相关数据。
-
SQL支持:结构化数据库使用SQL进行管理和查询。SQL是一种标准化的查询语言,能够使用户轻松地检索和操作数据。
-
ACID事务支持:结构化数据库支持ACID事务,确保数据的一致性和完整性。
常见的结构化数据库包括MySQL、Oracle、SQL Server等。结构化数据库主要用于事务性应用程序和数据处理应用程序,例如企业资源计划(ERP)和客户关系管理(CRM)系统。这些应用程序需要处理结构化数据,并且需要确保数据的一致性和完整性。
非结构化数据库
非结构化数据库是一种没有预定义数据结构的数据库,它们的数据存储方式是基于文档、键值对或图形的,不同的非结构化数据库使用的数据存储方式可能不同。非结构化数据库不需要事先定义数据结构,它们的数据可以动态添加和删除,非常适合存储大量复杂和多层次的数据。
非结构化数据库的特点如下:
-
数据灵活性:非结构化数据库的数据存储格式更灵活,可以存储各种类型的数据,包括文本、图像、音频、视频等。
-
高性能:非结构化数据库通常能够更快地访问和处理数据,因为它们的数据存储方式更为灵活,使得查询效率更高。
-
可扩展性:非结构化数据库通常可以更好地扩展,因为它们不需要预定义表结构。
-
没有固定查询语言:非结构化数据库没有像SQL一样的标准化查询语言,而是使用API和查询语句来访问和操作数据。
非结构化数据库可以分为几种不同的类型,包括:
-
文档数据库:文档数据库存储的是基于文档的数据,例如JSON或XML格式。文档数据库的查询通常是基于键值对的。常见的文档数据库包括MongoDB、Couchbase、RavenDB等。
-
键值数据库:键值数据库存储的是基于键值对的数据,通常用于缓存和存储大量的简单数据。常见的键值数据库包括Redis、Amazon DynamoDB、Riak等。
-
列式数据库:列式数据库将数据存储在列中,而不是行中,这使得它们能够快速地查询和分析大量数据。常见的列式数据库包括Apache Cassandra、HBase等。
-
图形数据库:图形数据库存储的是基于图形结构的数据,通常用于存储和查询关系和连接。常见的图形数据库包括Neo4j、ArangoDB等。
以下是常见的几种 NoSQL 数据库之间的对比:
特性 MongoDB Cassandra Redis Couchbase HBase 数据模型 文档型 列族型 键值型 文档型 列族型 支持 ACID 事务 支持 仅在单独的分区上支持 不支持 支持 不支持 数据分布 支持分片 支持分布式集群 不支持分片 支持分片 支持分布式集群 备份与恢复 支持备份和恢复 支持增量备份和快照 支持备份和恢复 支持备份和恢复 支持备份和恢复 索引 支持二级索引 支持二级索引 支持多种索引 支持二级索引 支持二级索引 适合场景 大数据量、高性能读写 分布式、高吞吐量写入 内存缓存、高速读写 强一致性、高可用性 适合实时读写大规模数据
结构化数据库和非结构化数据库
以下是结构化数据库和非结构化数据库的对比表格:
特性 | 结构化数据库 | 非结构化数据库 |
---|---|---|
数据模型 | 关系型模型,基于表格的结构 | 非关系型模型,没有固定的结构,可以是文档、键值、图形等 |
数据存储 | 通常使用 SQL 语言存储和检索数据 | 不使用 SQL 语言存储和检索数据 |
数据规模 | 适合处理小规模、高度结构化的数据 | 适合处理大规模、非结构化的数据 |
数据一致性 | 强一致性,可以保证数据的完整性和准确性 | 最终一致性,数据的一致性和准确性不能保证 |
数据处理 | 常用于在线事务处理(OLTP)场景 | 常用于在线分析处理(OLAP)场景 |
可扩展性 | 通常采用垂直扩展(增加更强大的硬件) | 通常采用水平扩展(增加更多的节点) |
代表性数据库 | MySQL、Oracle、SQL Server | MongoDB、Cassandra、Redis |
MongoDB介绍
MongoDB是一种流行的文档型数据库管理系统,它是一个开源、跨平台的数据库系统,支持在分布式集群上进行横向扩展。MongoDB使用类似于JSON的BSON(二进制JSON)格式来存储数据,它支持复杂的查询和索引,可以处理大量数据并具有高可用性和自动分片等特性。MongoDB的灵活性和可扩展性使得它在各种不同的应用场景中被广泛使用,如Web应用程序、大数据、物联网等。
MongoDB的主要特点如下:
- 数据模型灵活:MongoDB使用文档型数据库模型,可以存储各种类型的数据,如文本、图像、视频、音频等,且可以随时添加、删除、修改数据结构,极大地提高了开发效率。
- 横向扩展性强:MongoDB支持在分布式集群上进行横向扩展,通过将数据和负载分散到多台服务器上,提高了系统的可用性和吞吐量。
- 高性能:MongoDB通过内存映射和其他技术实现了高效的数据访问和查询,能够快速地处理大量数据。
- 高可用性:MongoDB通过副本集和分片技术实现了高可用性和容错性,即使某台服务器出现故障,整个系统也能够继续正常运行。
- 开源和社区支持:MongoDB是一个完全开源的项目,拥有庞大的社区支持和开发者基础,使得它能够快速地适应新的技术和应用场景。
安装与配置
下载安装包
MongoDB官网的下载页面上下载本地版本的
MongoDB。以下是下载MongoDB本地版本的步骤:
打开MongoDB官网https://www.mongodb.com/try/download/community 点击“Download”进入下载页面。
-
在下载页面中,选择适合的操作系统(如Windows、macOS或Linux)和MongoDB的版本号。如果不确定应该选择哪个版本,可以选择最新版本。
-
选择需要下载的版本后,会看到两个可用的下载选项:MSI和ZIP。如果使用的是Windows操作系统,建议下载MSI版本。如果使用的是Linux或macOS操作系统,建议下载ZIP版本。
安装
Windows
-
msi
-
双击安装包
mongodb-windows-x86_64-4.4.4-signed.msi
进行安装,根据提示完成安装过程。 -
将MongoDB的安装目录添加到系统环境变量中。默认情况下,MongoDB会被安装到
C:\Program Files\MongoDB\Server\<version>
目录下,其中<version>
是您所安装的MongoDB版本号。您可以按以下步骤将MongoDB的安装目录添加到系统环境变量中:a. 右键单击“此电脑”(或“我的电脑”),选择“属性”。
b. 点击“高级系统设置”。
c. 在“系统属性”窗口中,点击“环境变量”。
d. 在“环境变量”窗口中,找到“系统变量”下的“Path”变量,双击打开。
e. 在“编辑环境变量”窗口中,点击“新建”。
f. 输入MongoDB的安装路径,例如
C:\Program Files\MongoDB\Server\<version>\bin
,然后点击“确定”。 -
打开命令提示符,输入以下命令以启动MongoDB:
mongod --dbpath C:\mongodb\data\db
其中,
--dbpath
参数指定MongoDB数据文件的存储路径。如果未指定该参数,则MongoDB会默认使用C:\data\db
目录作为数据文件存储路径。 -
-
zip
-
下载MongoDB的Zip格式包,例如
mongodb-win32-x86_64-4.4.4.zip
。 -
解压MongoDB的Zip格式包到一个目录,例如
C:\mongodb
。 -
将MongoDB的安装目录添加到系统环境变量中。您可以按以下步骤将MongoDB的安装目录添加到系统环境变量中:
a. 右键单击“此电脑”(或“我的电脑”),选择“属性”。
b. 点击“高级系统设置”。
c. 在“系统属性”窗口中,点击“环境变量”。
d. 在“环境变量”窗口中,找到“系统变量”下的“Path”变量,双击打开。
e. 在“编辑环境变量”窗口中,点击“新建”。
f. 输入MongoDB的安装路径,例如
C:\mongodb\bin
,然后点击“确定”。 -
打开命令提示符,输入以下命令以启动MongoDB:
-
mongod --dbpath C:\mongodb\data\db
其中,--dbpath
参数指定MongoDB数据文件的存储路径。如果未指定该参数,则MongoDB会默认使用C:\data\db
目录作为数据文件存储路径。
Linux
- 打开终端,并切换到包含MongoDB压缩包的目录。
- 使用以下命令解压MongoDB压缩包:
tar -zxvf mongodb-linux-x86_64-<version>.tgz
其中<version>
是您下载的MongoDB版本号。
- 将解压后的文件夹移动到指定位置。例如,将MongoDB文件夹移动到
/usr/local/
目录下,使用以下命令:
sudo mv mongodb-linux-x86_64-<version> /usr/local/mongodb
- 配置环境变量。打开
~/.bashrc
或~/.bash_profile
文件,并添加以下行:
export PATH=/usr/local/mongodb/bin:$PATH
- 保存并关闭文件,然后使用以下命令使环境变量生效:
source ~/.bashrc
- 启动MongoDB。使用以下命令启动MongoDB:
mongod --dbpath \home\data\mongodb
Mongodb 配置项
下面是一份mongod.conf
的示例代码,包括了各个配置项的详细说明:
yamlCopy code# mongod.conf
# 系统日志配置
systemLog:
destination: file # 日志输出到文件
path: /var/log/mongodb/mongod.log # 日志文件路径
logAppend: true # 采用追加模式
quiet: false # 关闭安静模式,开启详细日志输出
# 网络配置
net:
port: 27017 # 监听的端口号
bindIp: 127.0.0.1 # 监听的IP地址,默认为所有可用IP地址
# 存储引擎配置
storage:
dbPath: /var/lib/mongodb # 数据文件存储路径
engine: wiredTiger # 存储引擎
# 进程管理配置
processManagement:
fork: true # 是否在后台运行
# 复制集配置
replication:
replSetName: rs0 # 复制集名称
# 安全认证配置
security:
authorization: enabled # 启用认证机制
在这个示例中,我们配置了系统日志、网络、存储引擎、进程管理、复制集和安全认证等多个方面的配置项。具体说明如下:
- 系统日志配置:将日志输出到文件,并指定了日志文件的存储路径。我们采用追加模式,并关闭了安静模式,以便输出详细的日志信息。
- 网络配置:指定了MongoDB监听的端口号为27017,并默认监听本地地址127.0.0.1。
- 存储引擎配置:指定了数据文件的存储路径为
/var/lib/mongodb
,并使用了wiredTiger存储引擎。 - 进程管理配置:将MongoDB配置为后台运行。
- 复制集配置:指定了复制集的名称为
rs0
。 - 安全认证配置:启用了认证机制,以增强MongoDB的安全性。
具体的配置项根据实际需求进行修改。修改mongod.conf
文件后,需要重启MongoDB才能使新的配置生效。
数据结构
数据库(Database)
数据库(Database)是 MongoDB 的最高级别的数据存储单位,可以包含多个集合(Collection),类似于关系型数据库中的数据库(Database)。
数据结构 | 描述 |
---|---|
集合(Collection) | 每个数据库可以包含多个集合,类似Mysql的表 |
文档(Document) | 每个集合包含多个文档,文档是 MongoDB 的最小数据单元 |
字段(Field) | 每个文档包含多个字段,类似于关系型数据库中的列 |
-
集合(Collection):
在 MongoDB 中,集合(Collection)是一组文档(Document)的无序集合。与关系型数据库中的表(Table)相比,集合不需要提前定义结构(Schema),也不需要定义表之间的关系。在集合中可以存储各种不同结构的文档,这使得 MongoDB 数据模型非常灵活,适用于各种类型的应用场景。
MongoDB 中的集合类似于关系型数据库中的表,但有以下区别:
- 集合不需要提前定义结构,文档可以有不同的字段和值。
- 集合是动态的,即当第一个文档插入时自动创建集合,不需要提前创建。
- 集合中的文档不需要有相同的字段,也不需要遵循相同的数据类型。
- 集合是基于文档的,而不是基于行的。
-
文档(Document):
文档(Document)是数据的基本单元,类似于关系型数据库中的行(Row)。文档是一个由字段和值组成的键值对(Key-Value Pair),可以存储各种不同的数据类型,例如字符串、整数、浮点数、布尔值、数组、日期等等。
与关系型数据库中的行相比,文档的结构非常灵活,可以随时添加或删除字段,也可以包含嵌套的文档和数组。这种灵活性使得 MongoDB 在处理非结构化数据时非常方便。
-
字段(Field):
在 MongoDB 中,一个文档(Document)就是一个数据记录,每个文档都由一个或多个字段(Field)组成。字段是文档中的最小单位,每个字段都包含一个键值对,键是字符串类型的字段名称,值可以是任何 BSON 数据类型,例如字符串、数字、布尔值、数组、日期时间等。
以下是 MongoDB 支持的常见数据类型以及它们的描述:
数据类型 描述 String 存储文本数据,最大长度为 16 MB Integer 存储整数,包括 32 位整数和 64 位整数 Double 存储浮点数 Boolean 存储布尔值 Object 存储嵌套文档 Array 存储数组 Date 存储日期和时间 ObjectId 存储文档的唯一标识符 Binary 存储二进制数据 Regular Expression 存储正则表达式 除了上述数据类型外,MongoDB 还支持一些高级数据类型,例如 GeoJSON、MinKey、MaxKey 等。这些数据类型在特定场景下会非常有用。
在 MongoDB 中,文档的字段类型是动态的,也就是说,在同一个集合中,不同的文档可以拥有不同的字段,而且这些字段的类型可以不同。这种灵活性使得 MongoDB 非常适合存储非结构化数据和半结构化数据。同时,这也带来了一些挑战,例如需要进行数据验证和数据一致性的管理。
基本操作
Shell操作
MongoDB 4.4版本之前使用mongo来操作数据库,后期版本使用mongosh 。
mongosh 是 MongoDB 官方推出的命令行工具,支持 MongoDB 4.4 及更高版本,提供了更好的交互体验和更多的功能,例如语法高亮、自动完成、内置实用程序等。
mongosh下载地址https://www.mongodb.com/try/download/shell,下载完成之后解压后,保存到上面配置的安装目录下,或者按照自己的想法放到任意位置。
- 连接 MongoDB 数据库
使用 mongosh 命令行工具连接 MongoDB 数据库,格式为:
mongosh mongodb://<username>:<password>@<host>/<database>
其中:
<username>
:用户名<password>
:密码<host>
:主机名或 IP 地址<database>
:要连接的数据库名称
例如,连接本地 MongoDB 数据库可以使用以下命令:
mongosh mongodb://localhost/test
#或者直接使用
mongosh
- 查看所有数据库
使用以下命令可以查看 MongoDB 中的所有数据库:
show databases
# 或者
show dbs
- 切换数据库
使用以下命令可以切换当前数据库:
use <database>
例如,切换到名为 mydb
的数据库:
use mydb
- 查看当前数据库中的所有集合
使用以下命令可以查看当前数据库中的所有集合:
show collections
- 插入数据insertOne / insertMany
使用以下命令可以向集合中插入一条文档:
db.<collection>.insertOne(<document>)
其中:
<collection>
:集合名称<document>
:要插入的文档数据,格式为 JSON 对象
例如,向名为 users
的集合中插入一条文档:
db.users.insertOne({ name: 'Alice', age: 30 })
在 mongosh
中进行批量插入数据可以使用 insertMany()
方法。例如,插入多个文档到 test
数据库中的 students
集合中:
db.users.insertMany([
{ name: "Alice", age: 20, gender: "female" },
{ name: "Bob", age: 21, gender: "male" },
{ name: "Charlie", age: 19, gender: "male" }
])
上述代码将会向 users集合中插入三个文档,每个文档都包含 name
、age
和 gender
三个字段。insertMany()
方法可以接受一个包含多个文档的数组作为参数,并且会返回一个包含插入结果的对象。
{
acknowledged: true,
insertedIds: {
'0': ObjectId("6405aa49d335c2829403f6a2"),
'1': ObjectId("6405aa49d335c2829403f6a3"),
'2': ObjectId("6405aa49d335c2829403f6a4")
}
}
- 查询数据
使用以下命令可以查询集合中的文档:
db.<collection>.find(<query>)
其中:
<collection>
:集合名称<query>
:查询条件,格式为 JSON 对象
例如,查询名为 Alice
的文档:
db.users.find({ name: 'Alice' })
db.users.find({ })
[
{ _id: ObjectId("6405a63ed335c2829403f6a1"), name: 'Alice', age: 30 },
{
_id: ObjectId("6405aa49d335c2829403f6a2"),
name: 'Alice',
age: 20,
gender: 'female'
},
{
_id: ObjectId("6405aa49d335c2829403f6a3"),
name: 'Bob',
age: 21,
gender: 'male'
},
{
_id: ObjectId("6405aa49d335c2829403f6a4"),
name: 'Charlie',
age: 19,
gender: 'male'
}
]
- 更新数据updateOne/updataMany
使用以下命令可以更新集合中的文档:
updateOne()
是 MongoDB 提供的更新单个文档的方法。
语法:
db.collection.updateOne(
<filter>,
<update>,
{
upsert: <boolean>,
writeConcern: <document>,
collation: <document>
}
)
参数说明:
-
<filter>
:查询需要更新的文档的筛选条件。常用的筛选符号如下:
$eq
: 匹配等于指定值的文档。$ne
: 匹配不等于指定值的文档。$gt
: 匹配大于指定值的文档。$gte
: 匹配大于或等于指定值的文档。$lt
: 匹配小于指定值的文档。$lte
: 匹配小于或等于指定值的文档。$in
: 匹配指定数组中任意值的文档。$nin
: 不匹配指定数组中任意值的文档。$and
: 逻辑与,同时满足多个条件。$or
: 逻辑或,满足多个条件之一。$not
: 反转筛选条件,匹配不符合条件的文档。$nor
: 逻辑非或,不满足多个条件之一。
-
<update>
:指定如何更新文档。 -
upsert
:可选,如果设置为true
,当查询条件的文档不存在时,会创建一个新文档。默认为false
。 -
writeConcern
:可选,指定写入操作的写入安全性。 -
collation
:可选,指定语言特定的比较规则。
例如,将名为 Alice
的文档的年龄更新为 31
:
db.users.updateOne({ name: 'Alice' }, { $set: { age: 31 } })
updateMany()是MongoDB用于更新多个文档的方法,可以将一个或多个文档的字段值更新为指定的值,或者使用更新操作符进行更新。
语法:
db.collection.updateMany(
<filter>,
<update>,
{
upsert: <boolean>,
writeConcern: <document>,
collation: <document>,
arrayFilters: [ <filterdocument1>, ... ]
}
)
参数说明:
-
filter
:指定更新文档的条件,与find
方法的query
参数类似。 -
update
:指定要更新的文档字段及值,可以使用更新操作符。 -
upsert
:可选,如果设置为true
,表示如果没有符合条件的文档则插入新的文档,默认为false
。 -
writeConcern
:可选,指定写入操作的安全级别。 -
collation
:可选,指定对文档进行排序、大小写不敏感的比较和字符映射的规则。 -
arrayFilters
:可选,如果更新的文档中包含嵌套数组,则使用该参数指定更新哪些子文档。update 更新操作符:
$set
:用于指定更新字段及其值。$unset
:用于从文档中删除一个或多个字段。$inc
:用于增加或减少一个数字型字段的值。$push
:用于将一个值添加到数组字段中。$addToSet
:用于将一个唯一的值添加到数组字段中。$pop
:用于从数组字段中删除第一个或最后一个元素。$pull
:用于从数组字段中删除指定的元素。$rename
:用于重命名一个字段。
示例:
将集合users
中年龄为25岁的用户的姓名改为“Tom”:
db.users.updateMany(
{ age: 25 },
{ $set: { name: "Tom" } }
)
将集合users
中年龄为25岁的用户的年龄加1:
db.users.updateMany(
{ age: 25 },
{ $inc: { age: 1 } }
)
将集合users
中所有用户的年龄减1:
db.users.updateMany(
{},
{ $inc: { age: -1 } }
)
- 删除数据
deleteOne(filter, options)
方法删除集合中匹配过滤条件的单个文档。如果多个文档匹配,只删除第一个匹配的文档。
db.collection.deleteOne(
<filter>,
{
writeConcern: <document>,
collation: <document>
}
)
<filter>
:(可选)删除条件,表示要删除的文档。writeConcern
:(可选)写入操作的写入安全性级别。collation
:(可选)指定要用于字符串比较的规则。
示例:
db.users.deleteOne({name: "John"})
deleteMany(filter, options)
方法从集合中删除匹配过滤条件的多个文档。
db.collection.deleteMany(
<filter>,
{
writeConcern: <document>,
collation: <document>
}
)
<filter>
:(可选)删除条件,表示要删除的文档。writeConcern
:(可选)写入操作的写入安全性级别。collation
:(可选)指定要用于字符串比较的规则。
示例:
db.users.deleteMany({age: {$lt: 18}})
在进行删除操作时,需要小心,因为它是永久性操作,一旦删除,数据将无法恢复。在删除之前,建议创建数据备份或在操作之前进行确认。
Java操作(MongoDB Java Driver)
Java 可以通过 MongoDB 官方提供的 Java 驱动程序(MongoDB Java Driver)来操作 MongoDB 数据库。
导入MongoDB Java Driver库文件
<!-- Maven依赖 -->
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-sync</artifactId>
<version>4.7.1</version>
</dependency>
import com.mongodb.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;
public class MongoDBExample {
public static void main(String[] args) {
// 创建 MongoClient 对象,并连接到 MongoDB 服务器
MongoClient mongoClient = MongoClients.create("mongodb://localhost:27017");
// 选择要操作的数据库
MongoDatabase database = mongoClient.getDatabase("mydb");
// 选择要操作的集合
MongoCollection<Document> collection = database.getCollection("mycollection");
// 插入文档
Document doc1 = new Document("name", "Alice").append("age", 25);
Document doc2 = new Document("name", "Bob").append("age", 30);
collection.insertMany(Arrays.asList(doc1, doc2));
// 关闭连接
mongoClient.close();
}
}
这个程序会连接到本地 MongoDB 服务器,并在名为 “mydb” 的数据库中的 “mycollection” 集合中插入两个文档,其中一个文档包含 “name” 和 “age” 两个字段,另一个文档也包含这两个字段。然后关闭连接。
- 插入文档
Document doc = new Document("name", "John Doe")
.append("age", 30)
.append("email", "johndoe@example.com");
collection.insertOne(doc);
- 查询文档
Document result = collection.find(Filters.eq("name", "John Doe")).first();
Filters
类提供了很多静态方法,这些方法可以用来创建各种查询条件,如相等、不相等、小于、大于等比较运算符、逻辑运算符(与、或、非)等。
下面是一些常用的Filters静态方法:
-
eq(String fieldName, Object value)
:相等比较,返回符合指定字段等于指定值的文档。 -
ne(String fieldName, Object value)
:不等比较,返回符合指定字段不等于指定值的文档。 -
gt(String fieldName, Object value
):大于比较,返回符合指定字段大于指定值的文档。 -
gte(String fieldName, Object value)
:大于等于比较,返回符合指定字段大于等于指定值的文档。 -
lt(String fieldName, Object value)
:小于比较,返回符合指定字段小于指定值的文档。 -
lte(String fieldName, Object value)
:小于等于比较,返回符合指定字段小于等于指定值的文档。 -
and(Bson... filters)
:逻辑与运算符,返回符合所有指定查询条件的文档。 -
or(Bson... filters)
:逻辑或运算符,返回符合任意指定查询条件的文档。 -
not(Bson filter)
:逻辑非运算符,返回符合指定查询条件取反后的文档。 -
regex()
:正则查询,用于在查询中匹配指定的正则表达式。
Bson query = Filters.and(
Filters.eq("name", "John"),
Filters.gt("age", 18)
);
// Execute the query
FindIterable<Document> results = collection.find(query);
这个查询将返回所有 name
字段等于 “John” 且 age
字段大于 18 的文档。
- 更新文档
collection.updateOne(Filters.eq("name", "John Doe"),
new Document("$set", new Document("age", 31)));
- 删除文档
collection.deleteOne(Filters.eq("name", "John Doe"));
- 导出文本
FileWriter writer = new FileWriter("d:\\output.txt");
MongoCursor<Document> cursor = collection.find().projection(Projections.exclude("_id" )).cursor();
JsonWriterSettings settings = JsonWriterSettings.builder()
.indent(false)
.build();
while (cursor.hasNext()) {
Document document = cursor.next();
System.out.println(document.toJson(settings));
writer.write(document.toJson() + "\n");
}
writer.close();
Projections
是MongoDB驱动程序中的一个类,用于在查询结果中只返回指定的字段,而不是返回整个文档。
常用的Projections方法及其含义如下:
include
:指定返回结果中需要包含哪些字段。如果还需要包含_id字段,则需要使用excludeId()方法。exclude
:指定返回结果中不需要包含哪些字段。excludeId
:指定返回结果中不需要包含_id字段。elemMatch
:指定返回结果中数组类型的字段只返回满足条件的元素,条件使用Filters.eq、Filters.gt、Filters.lt等方法构建。
下面是一个使用Projections
进行投影查询的例子:
MongoCollection<Document> collection = database.getCollection("mycollection");
Bson filter = Filters.eq("age", 30);
Bson projection = Projections.fields(Projections.include("name", "age"), Projections.excludeId());
FindIterable<Document> result = collection.find(filter).projection(projection);
在上述代码中,通过Projections.fields()方法指定了需要返回的字段(name和age),并且排除了_id字段。最后使用projection()方法将该投影查询应用于find()方法的结果中。
JsonWriterSettings
是 MongoDB Java Driver 中的一个类,用于配置 JsonWriter
的行为。JsonWriter
是将 MongoDB 文档序列化为 JSON 格式的类。在 MongoDB 4.4 以前的版本中,JsonWriter
与 BsonWriter
是分开的,分别用于序列化为 JSON 格式和 BSON 格式。而在 MongoDB 4.4 以后的版本中,它们被合并为一个类,名为 BsonDocumentWriter
,并且支持将文档序列化为多种格式。
以下是 JsonWriterSettings
中一些重要的属性:
indent
:是否缩进输出,默认为 false。indentCharacters
:缩进使用的字符,默认为空格。newLineCharacters
:换行使用的字符,默认为系统默认的换行符。maxLength
:JSON 字符串最大长度,默认为 0,表示不限制长度。escapeNonAsciiCharacters
:是否将非 ASCII 字符进行转义,默认为 false。dateTimeConverter
:日期转换器,默认为DefaultDateTimeConverter
,可以通过实现DateTimeConverter
接口来实现自定义的日期转换。outputMode
:输出模式,默认为STRICT
,可以选择RELAXED
或SHELL
模式。
使用 JsonWriterSettings
,可以对 MongoDB 文档的序列化行为进行灵活的配置,以满足不同的需求。
Spring boot 操作
pom增加一下依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
配置文件增加
spring:
data:
mongodb:
uri: mongodb://username:password@localhost:27017/mydatabase
或者
spring:
data:
mongodb:
uri: mongodb://localhost:27017/mydatabase
username: your-username
password: your-password
然后增加一个MongoTemplate 就可以使用了
插入
@Autowired
MongoTemplate mongoTemplate ;
@PostMapping("/insert")
public void insert(){
mongoTemplate.insert("{'a':1}","test");
}
删除
//remove 和 findAllAndRemove 区别,第二个会将删除的document以列表方式返回过来
Query query = new Query(Criteria.where("age").is("18"));
mongoTemplate.remove(query, "person");
List<Person> person = mongoTemplate.findAllAndRemove(query, "person");
}
查询
@PostMapping("/query")
public void query() {
// 删除
Query query = new Query(Criteria.where("age").is("18"));
List<Document> person = mongoTemplate.find(query, Document.class, "person");
System.out.println(person);
}
修改
@PostMapping("/update")
public void update() {
// 修改
Query query = new Query(Criteria.where("age").is("18"));
Update update = new Update().set("status", "minor");
mongoTemplate.updateMulti(query, update, Person.class);
}
高级
地理空间数据
地理空间数据在MongoDB中可以使用GeoJSON格式进行存储和查询。MongoDB提供了丰富的地理空间查询操作和索引功能,可以方便地处理地理位置相关的数据。
在MongoDB中,你可以使用GeoJSON对象来表示地理空间数据。GeoJSON是一种用于表示地理特征和位置的开放标准,它使用JSON格式来描述地理信息。
以下是一些常见的地理空间查询操作和索引功能:
创建地理空间索引:
@Autowired
private MongoTemplate mongoTemplate;
public void createGeospatialIndex() {
mongoTemplate.indexOps("locations").ensureIndex(new GeospatialIndex("location"));
}
在上述示例中,我们使用indexOps()方法获取集合的索引操作对象,然后使用ensureIndex()方法创建地理空间索引。GeospatialIndex类表示地理空间索引,传入要创建索引的字段名,这里是"location"。
查询附近的位置:
@Autowired
private MongoTemplate mongoTemplate;
public List<Document> findNearbyLocations(Point center, double maxDistance) {
NearQuery nearQuery = NearQuery.near(center).maxDistance(maxDistance, Metrics.KILOMETERS);
GeoResults<Document> results = mongoTemplate.geoNear(nearQuery, Document.class);
return results.getContent();
}
在上述示例中,我们使用geoNear()方法执行附近位置的查询。NearQuery对象表示附近查询,通过near()方法指定中心点的坐标,然后使用maxDistance()方法指定最大距离和单位(这里是公里)。
查询包含在多边形区域内的位置:
@Autowired
private MongoTemplate mongoTemplate;
public List<Document> findLocationsWithinPolygon(Polygon polygon) {
Query query = Query.query(Criteria.where("location").within(polygon));
return mongoTemplate.find(query, Document.class);
}
查询附近的位置:
@Autowired
private MongoTemplate mongoTemplate;
public List<Document> findNearbyLocations(Point center, double maxDistance) {
NearQuery nearQuery = NearQuery.near(center).maxDistance(maxDistance, Metrics.KILOMETERS);
GeoResults<Document> results = mongoTemplate.geoNear(nearQuery, Document.class);
return results.getContent();
}
查询两个位置之间的距离:
@Autowired
private MongoTemplate mongoTemplate;
public Distance calculateDistance(Point location1, Point location2) {
Distance distance = mongoTemplate.geoDist("locations", location1, location2);
return distance;
}
数据聚合操作
在MongoDB中,数据聚合操作是一种强大的工具,用于对文档进行多个阶段的数据处理和转换,以生成复杂的聚合结果。MongoDB提供了聚合管道(Aggregation Pipeline)来执行这些聚合操作。
聚合管道是一个由多个阶段组成的工作流程,每个阶段都对输入文档进行某种转换或操作,并将结果传递给下一个阶段。以下是一些常用的聚合操作阶段:
- $match:用于筛选符合指定条件的文档。
- $group:用于根据指定的字段对文档进行分组,并进行聚合操作,如计数、求和、平均值等。
- $sort:用于对文档进行排序操作。
- $project:用于选择要返回的字段,并可以对字段进行重命名、计算新字段等操作。
- $limit:用于限制返回结果的文档数量。
- $skip:用于跳过指定数量的文档。
- $unwind:用于展开数组字段,将数组中的每个元素作为单独的文档处理。
- $lookup:用于在不同的集合之间执行类似SQL中的join操作,将匹配的文档合并到结果中。
这些是聚合管道中常用的一些阶段,你可以根据需要组合和使用这些阶段来执行复杂的数据聚合操作。以下是一个使用聚合管道进行数据聚合的示例:
db.collection.aggregate([
{ $match: { age: { $gte: 18 } } },
{ $group: { _id: "$gender", count: { $sum: 1 } } },
{ $sort: { count: -1 } },
{ $limit: 5 }
])
在上述示例中,我们首先使用$match 阶段筛选出年龄大于等于18的文档,然后使用$group阶段按性别进行分组,并计算每个性别的文档数量。接下来,使用$sort阶段按文档数量降序排序,然后使用$limit阶段限制返回结果的文档数量为5。
假设我们有一个名为orders的集合,其中包含了客户的订单信息,每个订单文档包含了客户ID、订单金额和订单日期等字段。我们想要进行以下聚合操作:
筛选出订单金额大于100的订单。
按照客户ID进行分组,并计算每个客户的订单总金额和订单数量。
对订单总金额进行降序排序。
选择前5个客户的订单总金额和订单数量。
以下是相应的聚合管道示例:
db.orders.aggregate([
{ $match: { amount: { $gt: 100 } } },
{ $group: { _id: "$customerId", totalAmount: { $sum: "$amount" }, count: { $sum: 1 } } },
{ $sort: { totalAmount: -1 } },
{ $limit: 5 },
{ $project: { _id: 0, customerId: "$_id", totalAmount: 1, count: 1 } }
])
在上述示例中,我们首先使用$match阶段筛选出订单金额大于100的订单。接下来,使用$group阶段按照客户ID进行分组,并计算每个客户的订单总金额和订单数量。然后,使用$sort阶段对订单总金额进行降序排序,使用$limit阶段限制返回结果的文档数量为5。最后,使用$project阶段选择要返回的字段,并对_id字段进行重命名。
通过这个聚合管道,我们可以获取到订单金额大于100的前5个客户的订单总金额和订单数量。
$unwind是MongoDB聚合管道中的一个阶段,用于展开数组字段。当文档中的某个字段是数组类型时,$unwind可以将数组中的每个元素拆分成单独的文档,从而方便后续的聚合操作。
下面是$unwind的使用示例:
假设我们有一个名为users的集合,其中的文档包含了用户信息和他们参加的活动列表。每个用户文档的activities字段是一个数组,包含了用户参加的多个活动。我们想要展开这个数组,并对每个活动进行分组统计。
db.users.aggregate([
{ $unwind: "$activities" },
{ $group: { _id: "$activities", count: { $sum: 1 } } }
])
$lookup是MongoDB聚合管道中的一个阶段,用于在不同的集合之间执行类似SQL中的join操作。它允许你在一个集合中查找与另一个集合相关联的文档,并将匹配的文档合并到结果中。
以下是$lookup的使用示例:
假设我们有两个集合:orders和customers。orders集合包含了客户的订单信息,每个订单文档中包含了客户ID。customers集合包含了客户的详细信息,每个客户文档中包含了客户的ID和其他字段,如姓名、地址等。
我们想要在查询订单信息时,将每个订单文档中的客户ID关联到customers集合中,获取客户的详细信息。
以下是使用$lookup的聚合管道示例:
db.orders.aggregate([
{
$lookup: {
from: "customers",
localField: "customerId",
foreignField: "_id",
as: "customerInfo"
}
}
])
在上述示例中,我们使用 l o o k u p 阶段来执行关联操作。 lookup阶段来执行关联操作。 lookup阶段来执行关联操作。lookup阶段有几个参数:
from:指定要关联的集合名称,这里是"customers"。
localField:指定当前集合中用于关联的字段,这里是"customerId",表示订单文档中的客户ID字段。
foreignField:指定关联集合中的字段,这里是"_id",表示关联集合中的文档ID字段。
as:指定将关联结果存储到一个新字段中的名称,这里是"customerInfo"。
通过这个聚合管道,我们可以获取到每个订单文档中关联的客户详细信息,并将其存储到"customerInfo"字段中。
需要注意的是,$lookup操作会返回一个数组,即使只有一个匹配的文档。如果你只需要返回一个匹配的文档,可以在$lookup后面添加$unwind阶段来展开数组。
java 实现
@Autowired
private MongoTemplate mongoTemplate;
public List<Document> performLookup() {
LookupOperation lookupOperation = LookupOperation.newLookup()
.from("customers") // 关联的集合名称
.localField("customerId") // 当前集合中用于关联的字段
.foreignField("_id") // 关联集合中的字段
.as("customerInfo"); // 将关联结果存储到一个新字段
Aggregation aggregation = Aggregation.newAggregation(
lookupOperation
);
AggregationResults<Document> results = mongoTemplate.aggregate(aggregation, "orders", Document.class);
return results.getMappedResults();
}
在上述示例中,我们使用了LookupOperation来创建$lookup阶段的操作。通过调用newLookup()方法可以创建LookupOperation对象,然后通过from()、localField()、foreignField()和as()方法来设置$lookup阶段的相关参数。
接下来,我们使用Aggregation.newAggregation()方法创建Aggregation对象,并将LookupOperation对象作为参数传递给Aggregation.newAggregation()方法。这样就将$lookup阶段添加到聚合管道中。
最后,我们使用mongoTemplate的aggregate()方法来执行聚合操作,并将结果映射为Document对象。
MongoDB还提供了许多其他的聚合操作和表达式,如$avg、$max、$min、$push等,以及一些高级功能,如管道的嵌套和变量的使用。
l
索引的创建与使用
在MongoDB中,索引是用于提高查询性能的重要工具。通过创建适当的索引,可以加快查询速度并优化数据库的性能。下面是关于索引的创建和使用的一些示例:
创建索引:
@Autowired
private MongoTemplate mongoTemplate;
public void createIndex() {
mongoTemplate.indexOps("collectionName").ensureIndex(new Index().on("fieldName", Sort.Direction.ASC));
}
// 创建联合索引
public void createCompoundIndex() {
Index index = new Index().on("field1", Sort.Direction.ASC).on("field2", Sort.Direction.DESC);
mongoTemplate.indexOps("collectionName").ensureIndex(index);
}
使用indexOps()方法获取集合的索引操作对象,然后使用ensureIndex()方法创建索引。Index对象表示要创建的索引,通过on()方法指定要创建索引的字段名,以及可选的排序方向。
查询优化:
@Autowired
private MongoTemplate mongoTemplate;
public List<Document> findDocuments() {
Query query = new Query().addCriteria(/* 查询条件 */);
query.with(Sort.by(Sort.Direction.DESC, "fieldName"));
query.limit(10);
query.skip(5);
return mongoTemplate.find(query, Document.class);
}
使用with()方法指定查询的排序字段和顺序。使用limit()方法设置查询结果的最大数量,使用skip()方法设置要跳过的结果数量。这些操作可以优化查询,并且当与索引一起使用时,可以进一步提高性能。
解释查询计划:
@Autowired
private MongoTemplate mongoTemplate;
public void explainQueryPlan() {
Query query = new Query().addCriteria(/* 查询条件 */);
Document executionStats = mongoTemplate.getCollection("collectionName").find(query.getQueryObject()).explain();
System.out.println(executionStats);
}
使用explain()方法获取查询计划的详细信息。这可以帮助我们了解查询是如何被执行的,以及是否使用了索引。
数据备份与恢复
在MongoDB中,你可以使用mongodump和mongorestore工具来执行数据备份和恢复操作。
要创建MongoDB数据库的备份,你可以使用mongodump命令。以下是一个示例:
mongodump --db 你的数据库名 --out /备份目录的路径
这个命令将创建指定数据库的备份,并将其存储在指定的目录中。
要恢复备份并将数据导入MongoDB中,你可以使用mongorestore命令。以下是一个示例:
mongorestore --db 你的数据库名 /备份目录的路径
安全性配置
在MongoDB中启用认证:
# 修改MongoDB配置文件
security:
authorization: enabled
创建用户并授权:
// 连接到admin数据库
use admin
// 创建用户
db.createUser({
user: "myUser",
pwd: "myPassword",
roles: [
{ role: "readWrite", db: "myDatabase" }
]
})
授权:
创建用户和角色:
// 连接到admin数据库
use admin
// 创建用户
db.createUser({
user: "myUser",
pwd: "myPassword",
roles: [
{ role: "readWrite", db: "myDatabase" }
]
})
分配角色给用户:
// 连接到admin数据库
use admin
// 分配角色给用户
db.grantRolesToUser("myUser", [
{ role: "read", db: "myDatabase" }
])
加密传输:
生成自签名证书和私钥:
openssl req -newkey rsa:2048 -new -x509 -days 365 -nodes -out mongodb-cert.crt -keyout mongodb-cert.key
在MongoDB配置文件中启用TLS/SSL:
# 修改MongoDB配置文件
net:
ssl:
mode: requireSSL
PEMKeyFile: /path/to/mongodb-cert.crt
PEMKeyPassword: myPassword
CAFile: /path/to/ca.crt
防火墙:
配置操作系统级别的防火墙规则(例如,使用iptables):
# 允许从特定IP地址访问MongoDB端口
sudo iptables -A INPUT -p tcp --dport 27017 -s 192.168.0.100 -j ACCEPT
# 其他规则...
# 默认拒绝所有其他访问
sudo iptables -A INPUT -j DROP
添加入站规则,允许从特定IP地址访问MongoDB端口。
审计日志:
启用审计日志:
# 修改MongoDB配置文件
auditLog:
destination: file
path: /path/to/audit.log
format: JSON
查看审计日志:
cat /path/to/audit.log
实际应用场景
社交网络应用
用户资料存储:MongoDB可以用于存储用户的个人资料信息,如用户名、密码、个人描述、头像等。MongoDB的灵活数据模型使得可以轻松地存储和查询用户的个人资料。
社交图谱:MongoDB适用于存储社交网络中的关系图谱,如用户之间的关注关系、好友关系、点赞和评论等。MongoDB的嵌入文档或引用文档的方式可以方便地表示这些关系。
时间线和动态消息:MongoDB可以用于存储用户发布的动态消息、状态更新或推文。MongoDB的文档模型和索引功能可以快速检索和展示用户的时间线。
消息和聊天:MongoDB可以用于存储用户之间的私信、聊天记录和通知。MongoDB的集合和查询功能可以实现聊天历史记录和通知功能。
帖子和评论:MongoDB适合存储社交网络中的帖子、文章或博客,并管理用户对这些内容的评论。MongoDB的文档模型和索引功能可以进行高效的查询和排序。
物联网应用
设备数据存储:MongoDB可以用于存储物联网设备生成的传感器数据、日志数据、设备状态等。你可以使用MongoDB的文档模型来灵活地存储和查询设备数据。
设备管理:MongoDB适用于存储和管理物联网设备的元数据,如设备ID、设备类型、位置信息、固件版本等。你可以使用MongoDB的文档模型来存储设备信息,并使用索引和查询功能来进行设备管理操作。
实时数据处理:MongoDB可以用于实时处理物联网设备生成的数据流,例如进行数据聚合、过滤、转换等操作。MongoDB的流水线聚合功能和实时更新功能可以支持实时数据处理需求。
设备监控和告警:MongoDB可以用于存储设备状态信息,并支持设备监控和告警功能。你可以使用MongoDB的文档模型和查询功能来实现设备状态的监控和告警逻辑。
可视化和分析:MongoDB可以与其他工具和平台集成,用于可视化和分析物联网数据。你可以使用MongoDB的连接器将数据导出到可视化工具或分析平台进行数据分析和可视化展示。
日志分析
日志存储:MongoDB可以用于存储大量的日志数据,如应用程序日志、服务器日志、网络日志等。你可以使用MongoDB的文档模型来灵活地存储和查询日志数据。
实时日志监控:MongoDB可以用于实时监控日志数据,例如实时查看应用程序的错误日志、异常日志等。你可以使用MongoDB的查询功能和实时更新功能来实现实时日志监控。
日志分析:MongoDB可以用于进行复杂的日志分析,例如按时间范围、关键字、日志级别等进行查询和聚合操作。你可以使用MongoDB的聚合框架和查询语言来分析日志数据。
日志可视化和报表:MongoDB可以与其他工具和平台集成,用于将日志数据可视化和生成报表。你可以使用MongoDB的连接器将数据导出到可视化工具或报表生成工具进行数据可视化和报表生成。
日志存档和归档:MongoDB可以用于存储历史的日志数据,并支持数据存档和归档功能。你可以使用MongoDB的数据管理功能来实现对日志数据的存储、压缩和备份。
内容管理系统
存储和管理内容:MongoDB可以用于存储和管理CMS中的各种内容,如文章、页面、图像、视频等。你可以使用MongoDB的文档模型来灵活地存储和查询内容数据。
多语言支持:MongoDB可以轻松地支持多语言内容,如多语言文章、多语言页面等。你可以使用MongoDB的嵌套文档或引用文档的方式来存储多语言内容。
版本控制:MongoDB可以用于实现内容的版本控制功能,如保存历史版本、撤销更改等。你可以使用MongoDB的更新操作和历史记录功能来实现版本控制逻辑。
搜索和检索:MongoDB的全文搜索功能和灵活的查询语言可以用于实现内容的搜索和检索功能。你可以使用MongoDB的文本索引和查询操作来实现搜索和过滤功能。
图片和视频管理:MongoDB可以用于存储和管理CMS中的图片和视频文件。你可以使用MongoDB的二进制数据类型来存储图像和视频文件,并使用MongoDB的查询和索引功能进行文件管理。
用户管理:MongoDB可以用于存储和管理CMS中的用户数据,如用户信息、权限、登录凭证等。你可以使用MongoDB的文档模型和查询功能来进行用户管理操作。
缓存和性能优化:MongoDB可以用于缓存CMS中的数据,以提高性能和响应速度。你可以使用MongoDB的内存映射和查询缓存等功能来优化CMS的性能。