MongoDB入门
- MongoDB是一种流行的NoSQL数据库系统,它使用了灵活的文档导向的模型来存储和管理数据。与传统的关系数据库管理系统(RDBMS)不同,MongoDB不需要固定的表结构,它允许数据记录在没有预先定义模式的情况下被存储。这意味着数据库的记录可以有不同的字段,这对于处理大量异构数据非常有用。
- MongoDB的数据结构类似于JSON对象,其格式称为BSON(Binary JSON),这种格式支持更丰富的数据类型。MongoDB提供了强大的查询语言,支持复杂的查询、索引、聚合操作等。它还具有高可扩展性,可以通过分片等技术实现水平扩展,支持大规模的数据存储和处理。
- MongoDB最初是用C++语言编写的。C++以其性能优势和系统级编程能力被广泛用于开发数据库系统,这使得MongoDB可以高效地处理数据操作和内存管理。尽管MongoDB的核心是用C++编写的,但它也支持多种语言的驱动,例如Python、Java、Node.js等,开发者可以使用这些驱动在不同的应用程序中与MongoDB交互。
- MongoDB 文档
核心特点
- 文档导向
- MongoDB是基于文档的,这意味着它管理的基本数据单元是文档,这些文档类似于JSON对象,使得数据的读写非常直观。
- 文档可以嵌套复杂的数据类型,如数组和文档。
- 动态模式
- 数据可以在没有固定结构的情况下被存储,这给应对不断变化的数据结构带来了极大的灵活性。
- 可扩展性
- MongoDB支持水平扩展,通过分片可以分布数据到多个服务器。
- 复制集确保数据的高可用性和冗余。
- 强大的查询语言
- 它支持丰富的查询操作,包括文档和字段级别的查询,以及正则表达式等。
- 索引优化
- 支持多种类型的索引,以优化查询速度,包括地理空间索引、全文索引等。
- 聚合管道
- MongoDB的聚合框架提供了一个功能丰富的数据处理管道,允许数据在多个阶段进行处理和转换。
- 格外的驱动支持
- 有多种编程语言的官方支持,如Python、Java、C#、Node.js、Ruby等。
- 存储过程
- 支持JavaScript编写的服务器端函数。
- 灵活的部署
- MongoDB可以在多种环境中运行,包括云平台服务。
- 丰富的资源
- MongoDB社区非常活跃,提供大量的资源和支持,从而简化了开发和维护的工作。
- 强大的交易支持
- 尽管是NoSQL数据库,MongoDB也支持多文档事务,类似于关系型数据库的ACID事务。
- 访问MongoDB的官方下载中心。
- 选择"Windows"作为操作系统,选择所需版本,然后点击"下载"。
- 运行下载的
.msi
安装程序,并跟随提示进行安装。 - 完成安装后,可以将MongoDB的安装目录添加到系统的PATH环境变量中,以便在任何命令行窗口中运行MongoDB。
- 你还需要手动创建一个数据库存储目录(默认是
C:\data\db
)。 - 启动MongoDB服务。在命令行中运行
mongod
。 - 要开始使用MongoDB,你可以在另一个命令行窗口中运行
mongo
来启动 MongoDB Shell。
- 对于macOS,可以使用Homebrew来安装MongoDB。如果还没有安装Homebrew,请先安装它。
- 打开终端。
- 运行
brew tap mongodb/brew
来添加MongoDB的官方Homebrew tap。 - 然后运行
brew install mongodb-community@7.0
来安装最新版本的MongoDB。 - 通过
brew services start mongodb-community@7.0
命令启动MongoDB服务。 - 使用
mongo
命令来连接MongoDB服务并打开MongoDB Shell。
对于Linux,安装步骤将因发行版本不同而有所变化。以下是基于Ubuntu的安装步骤:
- 导入MongoDB公钥。这样可以确保deb软件包的一致性和真实性。
1
2
3curl -fsSL https://pgp.mongodb.com/server-7.0.asc | \
sudo gpg -o /usr/share/keyrings/mongodb-server-7.0.gpg \
--dearmor - 创建列表文件
1
echo "deb [ arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server-7.0.gpg ] https://repo.mongodb.com/apt/ubuntu jammy/mongodb-org/7.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-7.0.list
- 重新加载本地包数据库
1
sudo apt-get update
- 安装MongoDB
1
sudo apt-get install -y mongodb-org
- 启动MongoDB服务
1
sudo systemctl start mongod
- 如果你想MongoDB随系统启动而自动运行,使用
1
sudo systemctl enable mongod
- 连接到MongoDB
1
mongo
MySQL与 MongoDB 对比
MySQL | MongoDB |
---|---|
database | db(数据库) |
table | collection(集合) |
一条数据 | document(文档) |
MongoDB 之 db 操作
-
创建数据库
MongoDB中并不需要显式创建数据库。当你首次向数据库中的集合(collection)插入一条文档(document)时,MongoDB会自动创建这个数据库。
1
2use myNewDatabase // 切换到名为myNewDatabase的数据库,如果不存在,则准备创建
db.myNewCollection.insertOne({a: 1}) // 向名为myNewCollection的集合插入一个文档,这将自动创建数据库和集合 -
选择数据库
使用
use
命令加上数据库名来选择数据库。1
use myDatabase // 切换到名为myDatabase的数据库
-
查看当前数据库
要查看当前选定的数据库,你可以使用
db
命令。1
db // 显示当前数据库
-
列出所有数据库
使用
show dbs
命令列出服务器上的所有数据库。1
show dbs // 列出所有可用的数据库
-
删除数据库
要删除当前选中的数据库,可以使用
db.dropDatabase()
命令。1
2use myOldDatabase // 首先切换到你想要删除的数据库
db.dropDatabase() // 删除当前选中的数据库 -
其他数据库级别的操作
- 查看数据库状态:
db.stats()
- 创建用户:
db.createUser()
- 查看数据库中的集合:
show collections
- 备份数据库:使用
mongodump
工具 - 恢复数据库:使用
mongorestore
工具
- 查看数据库状态:
MongoDB 之 collection 操作
-
查看所有集合
要查看当前数据库中的所有集合,可以使用
show collections
命令。1
show collections
在 MongoDB 中,运行此命令会列出当前选定数据库中的所有集合的名称。
-
创建集合
虽然 MongoDB 会在你第一次向集合插入文档时自动创建集合,但如果你需要创建一个具有特定选项(例如固定大小或索引)的集合,可以使用
db.createCollection()
方法来显式创建它。1
db.createCollection("myNewCollection")
你还可以传递一个选项对象来指定其它属性,例如设置集合为固定大小。
1
db.createCollection("myCappedCollection", { capped: true, size: 100000 })
在这个例子中,
myCappedCollection
是一个固定大小的集合,其大小上限是100,000字节。 -
删除集合
- 使用
db.collection.drop()
方法来删除一个集合。1
db.myOldCollection.drop()
- 这条命令将会删除名为
myOldCollection
的集合。如果操作成功,它将返回true
;如果你尝试删除一个不存在的集合,它将返回false
。 - 注意:删除集合是不可逆的,并且会同时删除集合中的所有文档。
- 使用
MongoDB 之 document 操作
-
插入文档
-
插入单个文档
使用
insertOne
方法来插入一个文档到指定的集合中。如果集合不存在,MongoDB会自动创建这个集合。1
2
3
4
5db.collectionName.insertOne({
name: "John Doe",
age: 30,
email: "johndoe@example.com"
})这个命令会在
collectionName
集合中插入一个包含name
、age
和email
字段的文档。 -
插入多个文档
使用
insertMany
方法插入多个文档到集合中。这个方法接收一个文档数组作为参数。1
2
3
4db.collectionName.insertMany([
{ name: "Jane Doe", age: 25, email: "janedoe@example.com" },
{ name: "Jim Beam", age: 35, email: "jimbeam@example.com" }
])这个命令会在
collectionName
集合中插入两个文档。 -
附加说明
- 在MongoDB中,每个插入的文档都会自动赋予一个
_id
字段,这是文档的唯一标识符。如果在插入文档时没有提供_id
字段,MongoDB会自动生成一个ObjectId类型的_id
字段。 - 插入文档后,MongoDB会返回一个结果对象,其中包含关于操作的信息,比如影响的文档数和文档的
_id
等。 - 例如,插入单个文档后的返回结果可能类似这样:
1
2
3
4{
"acknowledged" : true,
"insertedId" : ObjectId("5f50c31e1c4ae8635237f460")
} - 同样,使用
insertMany
插入多个文档时,你会得到每个被插入文档的_id
的列表。 - 请注意,文档的字段可以是各种数据类型,不仅限于字符串或数字,还可以是数组、另一个文档或者甚至是二进制数据等。
- 在MongoDB中,每个插入的文档都会自动赋予一个
-
-
查询文档
-
查询所有文档
使用
find()
方法不带任何参数就可以查询集合中的所有文档。1
db.collectionName.find()
这会显示
collectionName
集合中的所有文档。 -
查询特定文档
添加查询条件作为
find()
方法的参数,可以查询满足特定条件的文档。1
db.collectionName.find({ age: { $gt: 25 } })
这个命令会查询
collectionName
集合中age
大于25的所有文档。 -
查询并返回特定字段
如果你只需要文档中的特定字段,可以在
find()
方法中指定第二个参数来包含或排除字段。1
db.collectionName.find({}, { name: 1, age: 1, _id: 0 })
这个命令会返回
collectionName
集合中所有文档的name
和age
字段,并排除_id
字段。 -
查询单个文档
使用
findOne()
方法可以返回满足查询条件的第一个文档。1
db.collectionName.findOne({ name: "John Doe" })
这个命令会查询
collectionName
集合中第一个名字为"John Doe"的文档。 -
使用查询操作符
查询操作符可以提供更强大的查询功能,如范围查询、正则表达式查询等。
1
db.collectionName.find({ age: { $lte: 30 } })
这个命令会查询
collectionName
集合中age
小于或等于30的所有文档。 -
多条件查询
-
$and
$and
操作符可以连接多个查询条件,只有同时满足所有条件的文档才会被查询到1
2
3
4
5
6
7
8
9
10
11# 查询年龄大于等于20且名字为"John"的文档
results = collection.find({
"$and": [
{"age": {"$gte": 20}},
{"name": "John"}
]
})
for document in results:
print(document) -
$or
$or
操作符至少满足其中一个条件的文档都会被查询到1
2
3
4
5
6
7
8
9
10
11# 查询名字为"John"或年龄小于30的文档
results = collection.find({
"$or": [
{"name": "John"},
{"age": {"$lt": 30}}
]
})
for document in results:
print(document) -
$nor
$nor
操作符用来查询不满足任何条件的文档1
2
3
4
5
6
7
8
9
10
11# 查询年龄不大于20且名字不为"John"的文档
results = collection.find({
"$nor": [
{"age": {"$gt": 20}},
{"name": "John"}
]
})
for document in results:
print(document) -
$not
$not
操作符用来查询不满足指定条件的文档1
2
3
4
5
6
7
8# 查询名字不以字母"J"开头的文档
results = collection.find({
"name": {"$not": {"$regex": "^J"}}
})
for document in results:
print(document) -
组合
$and
与$or
你也可以在同一个查询中组合使用
$and
和$or
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16# 查询年龄大于20且名字为"John"或者年龄小于30的文档(注意优先级和分组)
results = collection.find({
"$and": [
{
"$or": [
{"name": "John"},
{"age": {"$lt": 30}}
]
},
{"age": {"$gt": 20}}
]
})
for document in results:
print(document)
-
-
排序查询结果
使用
sort()
方法对查询结果进行排序。1
db.collectionName.find().sort({ age: -1 })
这个命令会返回
collectionName
集合中的所有文档,结果按age
字段降序排序。 -
限制查询结果数量
使用
limit()
方法限制查询结果的数量。1
db.collectionName.find().limit(5)
这个命令会返回
collectionName
集合中的前5个文档。 -
跳过指定数量的文档
使用
skip()
方法跳过查询结果中的指定数量的文档。1
db.collectionName.find().skip(5)
这个命令会跳过
collectionName
集合中的前5个文档,并返回之后的文档。 -
链式使用查询方法
find()
方法返回的是一个游标,你可以链式调用sort()
、limit()
和skip()
方法。1
db.collectionName.find().sort({ age: 1 }).limit(5).skip(10)
这个命令会查询
collectionName
集合,跳过前10个文档,然后按age
升序排序,并且只返回接下来的5个文档。
-
-
更新文档
-
更新单个文档
使用
updateOne
方法可以更新满足条件的第一个文档。你需要提供一个查询条件和要更新的字段。1
2
3
4db.collectionName.updateOne(
{ name: "John Doe" },
{ $set: { email: "john.doe@newdomain.com" } }
)这个命令会在
collectionName
集合中查找第一个名为"John Doe"的文档,并更新其email
字段。 -
更新多个文档
使用
updateMany
方法可以更新所有满足条件的文档。1
2
3
4db.collectionName.updateMany(
{ age: { $gt: 30 } },
{ $set: { status: "senior" } }
)这个命令会更新
collectionName
集合中所有age
大于30的文档,为他们添加或更新status
字段为 “senior”。 -
替换文档
使用
replaceOne
方法可以替换满足条件的第一个文档。1
2
3
4db.collectionName.replaceOne(
{ name: "John Doe" },
{ name: "John Doe", age: 50, status: "senior" }
)这个命令会在
collectionName
集合中查找第一个名为 “John Doe” 的文档,并完全替换它(除了_id
字段,除非你显式地也替换了它)。 -
原子操作符
MongoDB提供一系列原子操作符来更新文档,如
$set
用于设置字段值,$inc
用于增加字段值,$push
用于数组字段添加元素等。1
2
3
4db.collectionName.updateOne(
{ name: "Jane Doe" },
{ $inc: { age: 1 } }
)这个命令会将
collectionName
集合中名为 “Jane Doe” 的文档的age
字段增加1。 -
更新文档的选项
updateOne
和updateMany
方法还接受额外的选项参数。例如,如果你想在没有匹配文档时插入一个新文档,可以使用upsert
选项。1
2
3
4
5db.collectionName.updateOne(
{ name: "New User" },
{ $set: { age: 30, status: "new" } },
{ upsert: true }
)如果找不到名为 “New User” 的文档,上面的命令将插入一个新文档。
-
注意事项
- 更新操作默认只作用于第一个匹配的文档(
updateOne
和replaceOne
);如果你需要更新多个文档,则应使用updateMany
。 - 更新操作不会修改文档的
_id
值。 - 如果更新命令导致文档字段的减少,那么这些字段将被删除。
- 使用
updateMany
时要特别小心,因为它会更新所有匹配的文档。
- 更新操作默认只作用于第一个匹配的文档(
-
-
删除文档
-
删除单个文档
使用
deleteOne
方法删除满足条件的第一个文档。1
db.collectionName.deleteOne({ name: "John Doe" })
这个命令会在
collectionName
集合中删除第一个名字为 “John Doe” 的文档。 -
删除多个文档
使用
deleteMany
方法删除所有满足条件的文档。1
db.collectionName.deleteMany({ status: "inactive" })
这个命令会删除
collectionName
集合中所有status
字段为 “inactive” 的文档。 -
删除所有文档
要删除集合中的所有文档,可以传递一个空的查询对象给
deleteMany
方法。1
db.collectionName.deleteMany({})
这会删除
collectionName
集合中的所有文档。请注意,这不会删除集合本身。 -
注意事项
- 在执行删除操作之前,请确保你有充分的备份,以防止数据丢失。
- 考虑到安全性,MongoDB不允许无条件删除集合中的所有文档;必须提供一个空的查询对象
{}
以指明你确实打算删除所有文档。 - 删除操作是不可逆的,一旦执行,被删除的文档将无法恢复。
- 对于大规模的删除操作,可能需要考虑对性能的影响,以及是否要在非高峰时段执行。
-
-
计数文档
-
使用
countDocuments()
这个方法提供了一个准确的文档数量,基于查询过滤器。
1
db.collectionName.countDocuments({ status: "active" })
以上命令会返回
collectionName
集合中状态为 “active” 的文档数量。 -
使用
estimatedDocumentCount()
这个方法提供了一个估算值,这通常更快,但不会考虑任何查询过滤器。
1
db.collectionName.estimatedDocumentCount()
以上命令会返回
collectionName
集合中的估算文档数量。 -
注意事项
countDocuments()
实际上会执行一个查询,并且对结果进行计数,因此如果集合很大且有复杂的查询条件,这可能会比较慢。estimatedDocumentCount()
方法基于集合的元数据迅速返回一个估算值,这个数字可能不会包括最近的集合更改,如果最近没有发生写入操作,那么这个方法返回结果非常快,适用于较大的数据集。countDocuments()
和estimatedDocumentCount()
在返回结果时的性能差异通常在于是否使用索引和集合的大小。
-
-
排序文档
-
排序单个字段
例如,如果你想要按照名字升序排序:
1
db.collectionName.find().sort({ name: 1 })
如果你想要按照名字降序排序:
1
db.collectionName.find().sort({ name: -1 })
-
排序多个字段
如果你想要按照多个字段进行排序,比如先按照年龄升序排序,如果年龄相同再按照名字升序排序:
1
db.collectionName.find().sort({ age: 1, name: 1 })
-
使用索引进行排序
为了提高排序操作的效率,尤其是在处理大数据集时,你应该考虑使用索引。如果排序的字段上有索引,MongoDB将能够更高效地进行排序操作。
-
注意事项
- 对于大量数据的排序操作,如果没有合适的索引,排序可能非常耗时。
- 在没有索引支持的情况下,MongoDB将所有文档加载到内存中进行排序。如果处理的数据量超过了系统的可用内存,这将导致性能问题。
- 如果排序操作耗尽了MongoDB的排序操作内存限制(默认是32MB),查询将会失败。你可以通过创建索引或增加内存限制来解决这个问题。
-
-
限制查询结果
-
限制查询结果
例如,如果你只想获取5个文档,你可以这样做:
1
db.collectionName.find().limit(5)
这个命令会返回
collectionName
集合中的前5个文档。 -
结合排序和限制
你还可以结合使用排序和限制,比如,如果你想获取分数最高的5个学生:
1
db.collectionName.find().sort({ score: -1 }).limit(5)
这将会按分数降序排序后,返回前5个文档。
-
结合跳过和限制以进行分页
如果你想实现分页效果,你可以结合使用
skip()
和limit()
方法。例如,如果每页显示5个文档,并且你想获取第二页的文档:1
db.collectionName.find().skip(5).limit(5)
这里,
skip(5)
会跳过前5个文档,即第一页的内容,而limit(5)
则限制了只返回5个文档,即第二页的内容。 -
注意事项
- 使用
limit()
方法可以避免发送太多的数据给客户端,这对于性能和带宽都是一个好处。 sort()
,skip()
, 和limit()
方法的组合通常用于实现分页功能,但请注意skip()
操作在大数据集合中可能会导致性能问题,因为它仍然需要遍历所有被跳过的文档。- 对于更高效的分页,特别是在处理大量数据时,可以考虑使用范围查询(range queries)来代替
skip()
。
- 使用
-
PyMongo 之 document 操作
-
插入文档
-
插入单个文档
要插入单个文档到MongoDB集合中,可以使用
insert_one()
方法。1
2
3
4
5
6
7
8
9
10
11
12
13# 定义要插入的单个文档
my_document = {
"name": "John Doe",
"age": 30,
"address": "123 Elm Street"
}
# 执行插入操作
insert_result = collection.insert_one(my_document)
# 打印插入文档的ID
print(f"Inserted document with id: {insert_result.inserted_id}") -
插入多个文档
如果你想一次性插入多个文档,可以使用
insert_many()
方法。1
2
3
4
5
6
7
8
9
10
11
12
13# 定义要插入的多个文档
my_documents = [
{"name": "Jane Doe", "age": 25, "address": "456 Maple Street"},
{"name": "Alice Johnson", "age": 28, "address": "789 Oak Street"},
{"name": "Bob Smith", "age": 32, "address": "101 Pine Street"}
]
# 执行插入操作
insert_result = collection.insert_many(my_documents)
# 打印插入文档的ID列表
print(f"Inserted documents with ids: {insert_result.inserted_ids}") -
说明
- 当使用
insert_one()
或insert_many()
方法时,PyMongo会自动在每个文档中添加一个_id
字段,用作该文档的唯一标识。如果文档中已经包含了_id
字段,则PyMongo将使用该值作为文档的标识。 - 在执行插入操作后,
insert_one()
和insert_many()
方法都会返回一个结果对象,该对象包含了插入操作的信息,例如inserted_id
或inserted_ids
属性,它们分别代表插入的单个文档的ID或多个文档的ID列表。
- 当使用
-
-
查询文档
-
查询单个文档
使用
find_one()
方法来查询单个文档。如果有多个文档匹配查询条件,find_one()
将返回第一个匹配的文档。1
2
3# 查询名字为"John Doe"的第一个文档
document = collection.find_one({'name': 'John Doe'})
print(document) -
查询多个文档
使用
find()
方法来查询多个文档。find()
返回一个可迭代的游标对象,可以遍历集合中所有匹配的文档。1
2
3
4
5
6
7# 查询所有文档
for doc in collection.find():
print(doc)
# 查询所有名字为"John Doe"的文档
for doc in collection.find({'name': 'John Doe'}):
print(doc) -
使用查询操作符
MongoDB 提供了多种查询操作符,例如
$lt
(小于),$gt
(大于),$eq
(等于), 等等,来精细化查询条件。1
2
3# 查询年龄大于25的所有文档
for doc in collection.find({'age': {'$gt': 25}}):
print(doc) -
限制查询结果数目
你可以结合使用
limit()
方法来限制查询结果的数目。1
2
3# 查询年龄大于25,但仅返回前两个文档
for doc in collection.find({'age': {'$gt': 25}}).limit(2):
print(doc) -
指定返回的字段
使用
projection
参数来指定返回的字段。1
2
3# 只返回name和age字段
for doc in collection.find({}, {'name': 1, 'age': 1, '_id': 0}):
print(doc)在这里,
1
表示包含字段,0
表示排除字段。_id
字段默认是包含的,除非明确排除。 -
排序查询结果
可以使用
sort()
方法对查询结果进行排序。1
2
3
4
5
6
7# 按年龄升序排序
for doc in collection.find().sort('age', pymongo.ASCENDING):
print(doc)
# 按年龄降序排序
for doc in collection.find().sort('age', pymongo.DESCENDING):
print(doc) -
find_one_and_delete
这个方法查找并删除一个文档。它返回被删除的文档。
1
2
3
4
5# 查找并删除名字为"John Doe"的第一个文档
deleted_document = collection.find_one_and_delete({'name': 'John Doe'})
# 输出被删除的文档
print(deleted_document) -
find_one_and_replace
这个方法查找一个文档并用另一个文档替换它。它返回原始文档,或者如果设置了
return_document
参数,则返回更新后的文档。1
2
3
4
5
6
7
8
9
10# 查找名字为"John Doe"的第一个文档,并用新的文档替换它
new_document = {'name': 'John Doe', 'age': 30, 'address': '123 Park Ave'}
replaced_document = collection.find_one_and_replace(
{'name': 'John Doe'},
new_document,
return_document=pymongo.ReturnDocument.AFTER
)
# 输出替换后的文档
print(replaced_document) -
find_one_and_update
这个方法查找一个文档并更新它。可以指定更新的具体操作,比如使用
$set
来修改字段。它返回原始文档,或者如果设置了return_document
参数,则返回更新后的文档。1
2
3
4
5
6
7
8
9
10# 查找名字为"John Doe"的第一个文档,并更新它的年龄
updated_document = collection.find_one_and_update(
{'name': 'John Doe'},
{'$set': {'age': 29}},
return_document=pymongo.ReturnDocument.AFTER
)
# 输出更新后的文档
print(updated_document)
-
-
更新文档
-
更新单个文档
使用
update_one()
方法来更新单个文档。你需要提供一个查询条件(用于找到需要更新的文档)和一个更新操作符(如$set
用于指定更新的字段和值)。1
2
3
4
5# 更新名字为"John Doe"的第一个匹配文档的年龄
result = collection.update_one({'name': 'John Doe'}, {'$set': {'age': 29}})
# 输出被更新文档的数量
print(f"Documents updated: {result.modified_count}") -
更新多个文档
使用
update_many()
方法来更新多个文档。和update_one()
使用相同的查询条件和更新操作符,但会更新所有匹配的文档。1
2
3
4
5# 更新所有名字为"John Doe"的文档的地址
result = collection.update_many({'name': 'John Doe'}, {'$set': {'address': '123 Main Street'}})
# 输出被更新文档的数量
print(f"Documents updated: {result.modified_count}") -
原子操作符
除了
$set
之外,还可以使用其他的原子操作符,比如$inc
用于增加数值字段,或$push
用于向数组字段添加元素。1
2
3
4
5
6
7# 将名为"John Doe"的文档的"visit_count"字段增加1
result = collection.update_one({'name': 'John Doe'}, {'$inc': {'visit_count': 1}})
print(f"Documents updated: {result.modified_count}")
# 向名为"John Doe"的文档的"tags"数组添加一个新元素
result = collection.update_one({'name': 'John Doe'}, {'$push': {'tags': 'new-tag'}})
print(f"Documents updated: {result.modified_count}") -
upsert 操作
如果你想在更新操作中进行 “upsert”(如果文档不存在则插入),你可以设置
upsert=True
。1
2
3
4
5# 如果找不到则插入新文档
result = collection.update_one({'name': 'Eve Adams'}, {'$set': {'age': 30}}, upsert=True)
print(f"Documents matched: {result.matched_count}")
print(f"Documents modified: {result.modified_count}")
print(f"Upserted ID: {result.upserted_id}")如果查询条件没有匹配任何文档,并且
upsert=True
,则MongoDB将插入一个包含查询条件和更新操作指定字段的新文档。
-
-
删除文档
-
删除单个文档
使用
delete_one()
方法可以删除一个与查询条件匹配的文档。如果有多个文档匹配,只有第一个会被删除。1
2
3
4
5# 删除名字为"John Doe"的第一个匹配文档
delete_result = collection.delete_one({'name': 'John Doe'})
# 输出被删除文档的数量
print(f"Documents deleted: {delete_result.deleted_count}") -
删除多个文档
使用
delete_many()
方法可以删除所有匹配查询条件的文档。1
2
3
4
5# 删除所有名字为"John Doe"的文档
delete_result = collection.delete_many({'name': 'John Doe'})
# 输出被删除文档的数量
print(f"Documents deleted: {delete_result.deleted_count}") -
删除所有文档
如果你想删除集合中的所有文档,可以传递一个空的查询对象给
delete_many()
方法。1
2
3
4
5# 警告:这将删除集合中的所有文档
delete_result = collection.delete_many({})
# 输出被删除文档的数量
print(f"All documents deleted: {delete_result.deleted_count}")请注意,在执行删除操作时要特别小心,因为这些操作是不可逆的。对于生产环境中的数据,通常建议先执行查询确认需要删除的文档,然后再进行删除操作。同时,定期备份数据库是一种好的习惯,以防止数据丢失。
-
-
排序文档
-
基本排序
你可以使用
sort()
方法来定义排序的字段和方向。使用pymongo.ASCENDING
作为升序,pymongo.DESCENDING
作为降序。1
2
3
4
5
6
7
8# 升序排序
documents = collection.find().sort('fieldname', pymongo.ASCENDING)
# 降序排序
documents = collection.find().sort('fieldname', pymongo.DESCENDING)
for document in documents:
print(document) -
多字段排序
如果你想根据多个字段进行排序,可以向
sort()
方法传递一个包含多个元组的列表,每个元组包含字段名称和方向。1
2
3
4
5
6
7
8# 根据多个字段进行排序,例如先按 age 升序,然后按 name 降序
documents = collection.find().sort([
('age', pymongo.ASCENDING),
('name', pymongo.DESCENDING)
])
for document in documents:
print(document) -
使用链式调用进行排序
在 PyMongo 中,可以通过对查询结果进行链式调用来进行多步骤的数据处理,包括排序。
1
2
3
4
5# 链式调用:先筛选年龄大于25的文档,然后按年龄升序排序
documents = collection.find({'age': {'$gt': 25}}).sort('age', pymongo.ASCENDING)
for document in documents:
print(document)
-
-
计数文档
在PyMongo中,你可以使用
count_documents()
方法来准确地统计满足特定查询条件的文档数量。如果你只需要一个大致的估计值,也可以使用estimated_document_count()
方法,它基于集合的元数据信息快速给出一个近似的文档数量。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23from pymongo import MongoClient
# 连接到MongoDB
client = MongoClient('mongodb://localhost:27017/')
# 选择数据库和集合
db = client['your_database']
collection = db['your_collection']
# 使用count_documents来计数满足条件的文档数量
# 例如,计数年龄大于20的文档
count = collection.count_documents({'age': {'$gt': 20}})
print("Number of documents where age is greater than 20:", count)
# 如果你想计数集合中所有的文档,可以传递一个空的查询对象
total_count = collection.count_documents({})
print("Total number of documents in the collection:", total_count)
# 使用estimated_document_count来快速估计集合中的文档总数
# 注意这不会应用任何过滤条件,并且可能不是完全准确的
estimated_count = collection.estimated_document_count()
print("Estimated total number of documents in the collection:", estimated_count)
查询条件操作符
操作符 | 描述 | 示例 |
---|---|---|
$eq |
等于(equal to) | {'age': {'$eq': 30}} 匹配年龄等于30的文档 |
$gt |
大于(greater than) | {'age': {'$gt': 30}} 匹配年龄大于30的文档 |
$gte |
大于等于(greater than or equal to) | {'age': {'$gte': 30}} 匹配年龄大于等于30的文档 |
$lt |
小于(less than) | {'age': {'$lt': 30}} 匹配年龄小于30的文档 |
$lte |
小于等于(less than or equal to) | {'age': {'$lte': 30}} 匹配年龄小于等于30的文档 |
$ne |
不等于(not equal to) | {'age': {'$ne': 30}} 匹配年龄不等于30的文档 |
$in |
在给定数组里(in) | {'age': {'$in': [25, 30, 35]}} 匹配年龄为25, 30或35的文档 |
$nin |
不在给定数组里(not in) | {'age': {'$nin': [25, 30, 35]}} 匹配年龄不为25, 30或35的文档 |
$or |
或条件(logical OR) | {'$or': [{'age': 20}, {'name': 'John'}]} 匹配年龄为20或名字为John的文档 |
$and |
与条件(logical AND) | {'$and': [{'age': {'$gt': 20}}, {'name': 'John'}]} 匹配年龄大于20并且名字为John的文档 |
$not |
非条件(logical NOT) | {'age': {'$not': {'$lt': 30}}} 匹配年龄不小于30的文档 |
$exists |
字段是否存在 | {'name': {'$exists': True}} 匹配包含name字段的文档 |
$regex |
正则表达式 | {'name': {'$regex': '^J'}} 匹配名字以"J"开头的文档 |
$type |
类型检查 | {'age': {'$type': 'int'}} 匹配年龄字段类型为integer的文档 |
-
安装 PyMongo
1
pip install pymongo
-
连接到 MongoDB
1
2
3
4from pymongo import MongoClient
# 创建MongoDB客户端连接对象
client = MongoClient('mongodb://localhost:27017/')如果 MongoDB 运行在不同的主机或端口上,你需要相应地调整连接字符串。
-
选择数据库和集合
连接到指定的数据库和集合:
1
2
3
4
5# 选择数据库
db = client['my_database']
# 选择集合
collection = db['my_collection']确保将
'my_database'
和'my_collection'
替换为实际的数据库和集合名称。 -
插入文档
插入一个或多个文档到集合中:
1
2
3
4
5
6
7
8# 插入单个文档
result = collection.insert_one({'name': 'Alice', 'age': 30})
# 插入多个文档
results = collection.insert_many([
{'name': 'Bob', 'age': 25},
{'name': 'Charlie', 'age': 35}
]) -
查询文档
查询集合中的文档:
1
2
3
4
5
6
7
8
9# 查询单个文档
user = collection.find_one({'name': 'Alice'})
# 查询所有匹配的文档
users = collection.find({'age': {'$gt': 25}})
for user in users:
print(user)其中
'$gt'
是一个查询操作符,意味着“大于”。 -
更新文档
更新集合中的一个或多个文档:
1
2
3
4
5# 更新单个文档
result = collection.update_one({'name': 'Alice'}, {'$set': {'age': 31}})
# 更新多个文档
results = collection.update_many({'age': {'$gt': 25}}, {'$inc': {'age': 1}})这里
'$set'
操作符用于设定字段的值,'$inc'
用于增加一个值。 -
删除文档
从集合中删除一个或多个文档:
1
2
3
4
5# 删除单个文档
result = collection.delete_one({'name': 'Bob'})
# 删除多个文档
results = collection.delete_many({'age': {'$lt': 30}})其中
'$lt'
是一个查询操作符,意味着“小于”。 -
索引
在集合上创建索引以提高查询效率:
1
2# 在'name'字段上创建索引
index_result = collection.create_index([('name', pymongo.ASCENDING)]) -
关闭连接
在所有操作完成后,关闭客户端连接:
1
client.close()
-
综合示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43from pymongo import MongoClient
# 假设你已经安装了pymongo: pip install pymongo
# 连接MongoDB,假设MongoDB在本地运行,默认端口27017
client = MongoClient('mongodb://localhost:27017/')
# 选择数据库'mydatabase',如果它不存在,将在第一次插入数据时自动创建
db = client['mydatabase']
# 选择集合(相当于关系数据库的表)'users'
collection = db['users']
# 插入一个文档(相当于关系数据库的记录)
user1 = {'name': 'Alice', 'age': 25}
collection.insert_one(user1)
# 插入多个文档
users = [
{'name': 'Bob', 'age': 30},
{'name': 'Charlie', 'age': 35}
]
collection.insert_many(users)
# 查询单个文档
print(collection.find_one({'name': 'Alice'}))
# 查询所有文档
for user in collection.find():
print(user)
# 更新文档
collection.update_one({'name': 'Alice'}, {'$set': {'age': 26}})
# 删除文档
collection.delete_one({'name': 'Bob'})
# 创建索引
collection.create_index([('name', 1)])
# 关闭MongoDB连接
client.close()这个脚本演示了以下操作:
- 连接到本地运行的 MongoDB 实例。
- 选择或创建一个名为
mydatabase
的数据库。 - 选择或创建一个名为
users
的集合。 - 向
users
集合中插入一个单独的文档。 - 向
users
集合中插入多个文档。 - 执行查询以寻找名为 “Alice” 的文档。
- 遍历并打印出
users
集合中的所有文档。 - 更新名为 “Alice” 的文档的年龄。
- 删除名为 “Bob” 的文档。
- 在
name
字段上创建一个索引以提高查询性能。 - 关闭与 MongoDB 的连接。