MongoDB 是一种NoSQL(非关系型)数据库,它以**文档(document)**的形式存储数据,而不是传统的表格形式。MongoDB 是开源的、高效的,尤其适用于需要处理大量数据和快速变化的数据场景。它的设计目标是提供灵活性、可扩展性和高性能。
使用 Docker 部署
拉取 MongoDB Docker 镜像
首先,您需要从 Docker Hub 上拉取 MongoDB 官方镜像。
bash
docker pull mongo
这将下载最新版本的 MongoDB 镜像。如果您需要特定版本,可以在命令后指定版本号,例如 mongo:4.4
。
运行 MongoDB 容器
使用以下命令启动 MongoDB 容器:
bash
docker run -d --name mongodb -p 27017:27017 -v ~/data/mongo:/data/db mongo
-d
:以后台模式运行容器。--name mongodb
:指定容器名称为mongodb
,你可以根据需要更改名称。-p 27017:27017
:将主机的 27017 端口映射到容器中的 27017 端口(MongoDB 的默认端口)。-v ~/data/mongo:/data/db
:将本地目录~/data/mongo
挂载到容器的/data/db
,用于持久化 MongoDB 数据。如果不指定,MongoDB 容器中的数据不会持久化。
验证 MongoDB 是否启动
执行以下命令查看 MongoDB 容器的运行状态:
bash
docker ps
您应该能看到 mongodb
容器在运行,并且其 27017 端口已暴露到主机。
连接到 MongoDB
现在,MongoDB 已经运行,您可以使用 MongoDB 客户端工具(如 mongo shell
、MongoDB Compass)连接到数据库。
-
使用 Mongo Shell 连接(确保你有安装 mongo 客户端):
bashmongo --host 127.0.0.1 --port 27017
-
或者通过 Python(pymongo)连接:
pythonfrom pymongo import MongoClient client = MongoClient('mongodb://localhost:27017/')
配置用户名和密码(可选)
如果您需要启用认证来保护 MongoDB,可以在启动容器时添加环境变量设置用户名和密码。
bash
docker run -d --name mongodb \
-p 27017:27017 \
-v ~/data/mongo:/data/db \
-e MONGO_INITDB_ROOT_USERNAME=admin \
-e MONGO_INITDB_ROOT_PASSWORD=admin123 \
mongo
在这种情况下,您需要使用设置的用户名和密码连接到 MongoDB:
bash
mongo --username admin --password admin123 --authenticationDatabase admin
检查日志
如果你遇到问题或想要查看 MongoDB 容器的日志,可以使用以下命令:
bash
docker logs mongodb
停止和删除 MongoDB 容器
-
停止容器:
bashdocker stop mongodb
-
删除容器:
bashdocker rm mongodb
连接 MongoDB 数据库
在开始任何数据库操作之前,您需要先建立与 MongoDB 的连接。MongoClient
是 PyMongo
中的主要接口,用于与 MongoDB 实例通信。
python
from pymongo import MongoClient
# 连接到 MongoDB(默认 localhost:27017)
client = MongoClient('mongodb://localhost:27017/')
# 选择数据库
db = client['my_database']
内存中模拟部署
mongomock
是一个模拟 MongoDB 的 Python 库,允许您在内存中创建 MongoDB 的操作环境,而无需真正的 MongoDB 服务器。mongomock
模拟了 MongoDB 的大部分操作,适用于测试和开发环境。
安装 mongomock
首先,安装 mongomock
库:
bash
pip install mongomock
连接内存中的 MongoDB
要在内存中连接 mongomock
,您只需使用 mongomock.MongoClient()
来替代实际的 MongoDB 连接。这样所有数据都将保存在内存中,而无需连接到物理的 MongoDB 服务器。
python
import mongomock
from pymongo import MongoClient
# 使用 mongomock 代替 MongoDB 连接
client = mongomock.MongoClient()
数据库操作
MongoDB 中的数据库操作是管理和组织数据的基础。在 PyMongo
中,我们可以轻松进行数据库的创建、选择、列出和删除等操作。
列出所有数据库
要查看 MongoDB 实例中的所有数据库,可以使用 list_database_names()
方法。这会返回一个包含数据库名称的列表。
python
from pymongo import MongoClient
# 连接到 MongoDB
client = MongoClient('mongodb://localhost:27017/')
# 列出所有数据库
databases = client.list_database_names()
print(databases)
-
输出示例 :
python['admin', 'local', 'my_database']
创建或选择数据库
MongoDB 是无模式的(schema-less),这意味着您不需要明确地创建数据库,只要您向该数据库中插入文档,它就会自动创建。要选择数据库,您只需通过 client['database_name']
访问它。
python
# 选择数据库(如果不存在,在插入文档时将自动创建)
db = client['my_database']
# 检查当前数据库名称
print(db.name) # 输出: my_database
此时,my_database
数据库实际上还没有创建,直到您向其中插入数据为止。
删除数据库
如果您需要删除某个数据库,可以使用 drop_database()
方法。它会从 MongoDB 实例中删除整个数据库及其包含的所有数据。
python
# 删除名为 'my_database' 的数据库
client.drop_database('my_database')
- 注意: 该操作是不可逆的,执行后所有数据将被删除。
集合操作
集合(collection
)是 MongoDB 中用于存储文档的类似表的结构。在 PyMongo
中,您可以轻松操作集合,进行创建、列出和删除等操作。
列出所有集合
要查看当前数据库中的所有集合,可以使用 list_collection_names()
方法。这将返回该数据库中所有集合的名称。
python
# 选择数据库
db = client['my_database']
# 列出所有集合
collections = db.list_collection_names()
print(collections)
-
输出示例 :
python['users', 'orders', 'products']
创建或选择集合
与数据库一样,MongoDB 也不会在创建集合时进行强制检查。您只需使用 db['collection_name']
来引用集合,MongoDB 会在插入文档时自动创建它。
python
# 选择集合(如果不存在,将在插入数据时自动创建)
collection = db['users']
# 检查当前集合名称
print(collection.name) # 输出: users
如果集合不存在,在第一次插入文档时将会自动创建。
删除集合
您可以使用 drop()
方法来删除集合。这将删除集合以及其中的所有数据。
python
# 删除集合 'users'
db.drop_collection('users')
- 注意: 该操作是不可逆的,删除集合后,其包含的所有文档都将被永久删除。
文档操作
MongoDB 中的文档是数据的基本单元,每个文档都是一个 BSON 格式的键值对集合。在 PyMongo
中,您可以进行各种文档操作,包括插入、删除、更新和查询。以下是这些操作的详细说明和示例。
插入文档
文档的插入操作可以通过 insert_one()
或 insert_many()
方法来完成。
-
插入单个文档 :
使用
insert_one()
方法向集合中插入单个文档。pythonfrom pymongo import MongoClient # 连接到 MongoDB client = MongoClient('mongodb://localhost:27017/') db = client['my_database'] collection = db['my_collection'] # 插入单个文档 document = {"name": "Alice", "age": 25, "city": "New York"} result = collection.insert_one(document) # 获取插入的文档的 ID print("Inserted document ID:", result.inserted_id)
-
插入多个文档 :
使用
insert_many()
方法向集合中插入多个文档。pythondocuments = [ {"name": "Bob", "age": 30, "city": "Los Angeles"}, {"name": "Charlie", "age": 35, "city": "Chicago"} ] result = collection.insert_many(documents) # 获取插入的文档的 ID 列表 print("Inserted document IDs:", result.inserted_ids)
删除文档
删除文档可以通过 delete_one()
和 delete_many()
方法进行。
-
删除单个文档 :
使用
delete_one()
方法删除集合中符合条件的第一个文档。pythonresult = collection.delete_one({"name": "Alice"}) # 输出删除操作的结果 print("Number of documents deleted:", result.deleted_count)
-
删除多个文档 :
使用
delete_many()
方法删除集合中所有符合条件的文档。pythonresult = collection.delete_many({"age": {"$lt": 30}}) # 删除年龄小于 30 的文档 # 输出删除操作的结果 print("Number of documents deleted:", result.deleted_count)
更新文档
更新文档可以通过 update_one()
和 update_many()
方法进行。update()
方法也可以实现,但推荐使用 update_one()
和 update_many()
。
-
更新单个文档 :
使用
update_one()
方法更新集合中符合条件的第一个文档。pythonresult = collection.update_one( {"name": "Bob"}, {"$set": {"age": 31}} ) # 输出更新操作的结果 print("Number of documents matched:", result.matched_count) print("Number of documents modified:", result.modified_count)
-
更新多个文档 :
使用
update_many()
方法更新集合中所有符合条件的文档。pythonresult = collection.update_many( {"city": "Chicago"}, {"$set": {"city": "Chi-Town"}} ) # 输出更新操作的结果 print("Number of documents matched:", result.matched_count) print("Number of documents modified:", result.modified_count)
-
使用更新操作符 :
MongoDB 提供了多种更新操作符,例如
$inc
、$set
、$unset
等。python# 增加年龄字段的值 collection.update_one({"name": "Charlie"}, {"$inc": {"age": 1}}) # 设置新的字段值 collection.update_one({"name": "Charlie"}, {"$set": {"status": "active"}}) # 删除字段 collection.update_one({"name": "Charlie"}, {"$unset": {"status": ""}})
查询文档
查询文档是 MongoDB 操作中最常见的任务之一。PyMongo
提供了强大的查询功能,通过 find_one()
和 find()
方法可以执行各种查询操作。
-
查找单个文档 :
使用
find_one()
方法查找集合中符合条件的第一个文档。如果没有匹配的文档,则返回None
。pythondocument = collection.find_one({"name": "Alice"}) print(document)
-
查找多个文档 :
使用
find()
方法查找集合中所有符合条件的文档。返回的是一个游标对象,可以通过迭代来访问结果。pythoncursor = collection.find({"age": {"$gt": 25}}) # 查找年龄大于 25 的所有文档 for document in cursor: print(document)
-
指定返回字段 :
使用投影来指定返回的字段。如果您只需要某些字段,可以在查询中指定。
pythoncursor = collection.find({"age": {"$gt": 25}}, {"name": 1, "city": 1, "_id": 0}) for document in cursor: print(document)
-
使用排序和限制结果 :
使用
sort()
方法对查询结果进行排序,使用limit()
方法限制结果数量。python# 按年龄升序排序,限制结果为前 5 个 cursor = collection.find().sort("age", pymongo.ASCENDING).limit(5) for document in cursor: print(document)
-
使用查询操作符 :
MongoDB 支持丰富的查询操作符,例如
$eq
、$ne
、$gt
、$lt
、$in
、$nin
等。以下是 MongoDB 查询操作符的功能与使用的详细表格:
操作符 功能 示例用法 $eq
等于 { "age": { "$eq": 25 } }
查找年龄等于 25 的文档。$ne
不等于 { "age": { "$ne": 25 } }
查找年龄不等于 25 的文档。$gt
大于 { "age": { "$gt": 25 } }
查找年龄大于 25 的文档。$gte
大于或等于 { "age": { "$gte": 25 } }
查找年龄大于或等于 25 的文档。$lt
小于 { "age": { "$lt": 25 } }
查找年龄小于 25 的文档。$lte
小于或等于 { "age": { "$lte": 25 } }
查找年龄小于或等于 25 的文档。$in
在指定值的数组中 { "age": { "$in": [25, 30, 35] } }
查找年龄在 25、30 或 35 中的文档。$nin
不在指定值的数组中 { "age": { "$nin": [25, 30, 35] } }
查找年龄不在 25、30 或 35 中的文档。$or
满足任意一个条件 { "$or": [ { "age": { "$lt": 25 } }, { "city": "New York" } ] }
查找年龄小于 25 或城市为 New York 的文档。$and
满足所有条件 { "$and": [ { "age": { "$gt": 25 } }, { "city": "New York" } ] }
查找年龄大于 25 且城市为 New York 的文档。$not
取反 { "age": { "$not": { "$gt": 25 } } }
查找年龄小于或等于 25 的文档。$exists
字段是否存在 { "name": { "$exists": true } }
查找包含name
字段的文档。$type
字段的数据类型 { "age": { "$type": "int" } }
查找age
字段数据类型为整数的文档。$regex
字段值匹配正则表达式 { "name": { "$regex": "^A", "$options": "i" } }
查找name
字段以 "A" 开头的文档(不区分大小写)。$elemMatch
匹配数组中至少一个元素 { "scores": { "$elemMatch": { "subject": "Math", "score": { "$gt": 80 } } } }
查找scores
数组中包含至少一个分数大于 80 且科目为 Math 的文档。$all
数组包含所有指定的值 { "tags": { "$all": ["urgent", "finance"] } }
查找tags
数组中同时包含 "urgent" 和 "finance" 的文档。$size
数组的长度 { "items": { "$size": 3 } }
查找items
数组长度为 3 的文档。python# 查找年龄等于 30 的文档 cursor = collection.find({"age": {"$eq": 30}}) for document in cursor: print(document) # 查找年龄在 20 到 30 之间的文档 cursor = collection.find({"age": {"$gt": 20, "$lt": 30}}) for document in cursor: print(document) # 查找城市在指定列表中的文档 cursor = collection.find({"city": {"$in": ["New York", "Los Angeles"]}}) for document in cursor: print(document)
嵌套文档操作
插入嵌套文档
使用 insert_one()
方法可以将嵌套文档直接插入集合中。
python
from pymongo import MongoClient
client = MongoClient('mongodb://localhost:27017/')
db = client['my_database']
collection = db['my_collection']
# 插入一个嵌套文档
document = {
"name": "Alice",
"address": {
"city": "New York",
"zipcode": "10001"
}
}
collection.insert_one(document)
查询嵌套文档
MongoDB 支持通过点符号来查询嵌套文档中的字段。
查询嵌套字段时,可以直接通过字段路径进行精确查询。例如,查找 address.city
是 "New York"
的文档:
python
query = {"address.city": "New York"}
cursor = collection.find(query)
for document in cursor:
print(document)
如果文档中包含嵌套文档数组,可以通过点符号和条件组合来查询。例如,查找 addresses
数组中包含 city
为 "San Francisco"
的文档:
python
query = {"addresses.city": "San Francisco"}
cursor = collection.find(query)
for document in cursor:
print(document)
更新嵌套文档
通过点符号和 $set
可以更新嵌套文档中的字段。
更新 address.city
为 "Los Angeles"
的操作如下:
python
collection.update_one(
{"name": "Alice"},
{"$set": {"address.city": "Los Angeles"}}
)
通过 $
操作符可以更新数组中的嵌套字段。如下所示,更新 addresses
数组中 city
为 "San Francisco"
的 zipcode
:
python
collection.update_one(
{"addresses.city": "San Francisco"},
{"$set": {"addresses.$.zipcode": "94105"}}
)
删除嵌套文档
使用 $unset
可以删除嵌套文档中的字段。
删除 address.zipcode
字段的操作如下:
python
collection.update_one(
{"name": "Alice"},
{"$unset": {"address.zipcode": ""}}
)
通过 $pull
操作符可以从数组中删除特定的嵌套文档。例如,删除 addresses
数组中 city
为 "San Francisco"
的文档:
python
collection.update_one(
{"name": "Bob"},
{"$pull": {"addresses": {"city": "San Francisco"}}}
)
索引操作
索引在 MongoDB 中用于加快查询速度,PyMongo
提供了创建和管理索引的功能。
创建索引
可以为集合中的字段创建索引:
python
collection.create_index([("name", 1)]) # 1 代表升序索引
列出索引
您可以列出集合中所有的索引:
python
indexes = collection.list_indexes()
for index in indexes:
print(index)
删除索引
删除指定的索引:
python
collection.drop_index("name_1") # "name_1" 是索引名称
聚合操作
MongoDB 提供了强大的聚合管道操作,用于处理数据的复杂查询和转换。PyMongo
支持 aggregate()
方法来执行聚合查询。
python
pipeline = [
{"$match": {"age": {"$gt": 25}}}, # 过滤条件
{"$group": {"_id": "$city", "average_age": {"$avg": "$age"}}} # 按照城市分组,计算平均年龄
]
result = collection.aggregate(pipeline)
for doc in result:
print(doc)
事务支持
对于涉及多个操作的原子性需求,MongoDB 支持事务。在事务中,所有的操作要么成功执行,要么失败回滚。
python
with client.start_session() as session:
with session.start_transaction():
collection.update_one({"name": "Bob"}, {"$set": {"age": 32}}, session=session)
collection.update_one({"name": "Charlie"}, {"$set": {"age": 36}}, session=session)
GridFS 文件存储
MongoDB 支持存储大文件或二进制数据,PyMongo
提供了 GridFS
用于存储超过 16MB 的大文件。
上传文件到 GridFS
python
from gridfs import GridFS
fs = GridFS(db)
file_id = fs.put(b"Some large binary data")
下载文件
python
file_data = fs.get(file_id).read()