【Python】PyMongo:MongoDB操作

MongoDB 是一种NoSQL(非关系型)数据库,它以**文档(document)**的形式存储数据,而不是传统的表格形式。MongoDB 是开源的、高效的,尤其适用于需要处理大量数据和快速变化的数据场景。它的设计目标是提供灵活性、可扩展性和高性能。

使用 Docker 部署

拉取 MongoDB Docker 镜像

首先,您需要从 Docker Hub 上拉取 MongoDB 官方镜像。

docker pull mongo

这将下载最新版本的 MongoDB 镜像。如果您需要特定版本,可以在命令后指定版本号,例如 mongo:4.4

运行 MongoDB 容器

使用以下命令启动 MongoDB 容器:

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 容器的运行状态:

docker ps

您应该能看到 mongodb 容器在运行,并且其 27017 端口已暴露到主机。

连接到 MongoDB

现在,MongoDB 已经运行,您可以使用 MongoDB 客户端工具(如 mongo shell、MongoDB Compass)连接到数据库。

  • 使用 Mongo Shell 连接(确保你有安装 mongo 客户端):

    mongo --host 127.0.0.1 --port 27017
    
  • 或者通过 Python(pymongo)连接

    from pymongo import MongoClient
    client = MongoClient('mongodb://localhost:27017/')
    

配置用户名和密码(可选)

如果您需要启用认证来保护 MongoDB,可以在启动容器时添加环境变量设置用户名和密码。

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:

mongo --username admin --password admin123 --authenticationDatabase admin

检查日志

如果你遇到问题或想要查看 MongoDB 容器的日志,可以使用以下命令:

docker logs mongodb

停止和删除 MongoDB 容器

  • 停止容器

    docker stop mongodb
    
  • 删除容器

    docker rm mongodb
    

连接 MongoDB 数据库

在开始任何数据库操作之前,您需要先建立与 MongoDB 的连接。MongoClientPyMongo 中的主要接口,用于与 MongoDB 实例通信。

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 库:

pip install mongomock

连接内存中的 MongoDB

要在内存中连接 mongomock,您只需使用 mongomock.MongoClient() 来替代实际的 MongoDB 连接。这样所有数据都将保存在内存中,而无需连接到物理的 MongoDB 服务器。

import mongomock
from pymongo import MongoClient

# 使用 mongomock 代替 MongoDB 连接
client = mongomock.MongoClient()

数据库操作

MongoDB 中的数据库操作是管理和组织数据的基础。在 PyMongo 中,我们可以轻松进行数据库的创建、选择、列出和删除等操作。

列出所有数据库

要查看 MongoDB 实例中的所有数据库,可以使用 list_database_names() 方法。这会返回一个包含数据库名称的列表。

from pymongo import MongoClient

# 连接到 MongoDB
client = MongoClient('mongodb://localhost:27017/')

# 列出所有数据库
databases = client.list_database_names()
print(databases)
  • 输出示例:
    ['admin', 'local', 'my_database']
    

创建或选择数据库

MongoDB 是无模式的(schema-less),这意味着您不需要明确地创建数据库,只要您向该数据库中插入文档,它就会自动创建。要选择数据库,您只需通过 client['database_name'] 访问它。

# 选择数据库(如果不存在,在插入文档时将自动创建)
db = client['my_database']

# 检查当前数据库名称
print(db.name)  # 输出: my_database

此时,my_database 数据库实际上还没有创建,直到您向其中插入数据为止。

删除数据库

如果您需要删除某个数据库,可以使用 drop_database() 方法。它会从 MongoDB 实例中删除整个数据库及其包含的所有数据。

# 删除名为 'my_database' 的数据库
client.drop_database('my_database')
  • 注意: 该操作是不可逆的,执行后所有数据将被删除。

集合操作

集合(collection)是 MongoDB 中用于存储文档的类似表的结构。在 PyMongo 中,您可以轻松操作集合,进行创建、列出和删除等操作。

列出所有集合

要查看当前数据库中的所有集合,可以使用 list_collection_names() 方法。这将返回该数据库中所有集合的名称。

# 选择数据库
db = client['my_database']

# 列出所有集合
collections = db.list_collection_names()
print(collections)
  • 输出示例:
    ['users', 'orders', 'products']
    

创建或选择集合

与数据库一样,MongoDB 也不会在创建集合时进行强制检查。您只需使用 db['collection_name'] 来引用集合,MongoDB 会在插入文档时自动创建它。

# 选择集合(如果不存在,将在插入数据时自动创建)
collection = db['users']

# 检查当前集合名称
print(collection.name)  # 输出: users

如果集合不存在,在第一次插入文档时将会自动创建。

删除集合

您可以使用 drop() 方法来删除集合。这将删除集合以及其中的所有数据。

# 删除集合 'users'
db.drop_collection('users')
  • 注意: 该操作是不可逆的,删除集合后,其包含的所有文档都将被永久删除。

文档操作

MongoDB 中的文档是数据的基本单元,每个文档都是一个 BSON 格式的键值对集合。在 PyMongo 中,您可以进行各种文档操作,包括插入、删除、更新和查询。以下是这些操作的详细说明和示例。

插入文档

文档的插入操作可以通过 insert_one()insert_many() 方法来完成。

  • 插入单个文档
    使用 insert_one() 方法向集合中插入单个文档。

    from 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() 方法向集合中插入多个文档。

    documents = [
        {"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() 方法删除集合中符合条件的第一个文档。

    result = collection.delete_one({"name": "Alice"})
    
    # 输出删除操作的结果
    print("Number of documents deleted:", result.deleted_count)
    
  • 删除多个文档
    使用 delete_many() 方法删除集合中所有符合条件的文档。

    result = 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() 方法更新集合中符合条件的第一个文档。

    result = 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() 方法更新集合中所有符合条件的文档。

    result = 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 等。

    # 增加年龄字段的值
    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

    document = collection.find_one({"name": "Alice"})
    print(document)
    
  • 查找多个文档
    使用 find() 方法查找集合中所有符合条件的文档。返回的是一个游标对象,可以通过迭代来访问结果。

    cursor = collection.find({"age": {"$gt": 25}})  # 查找年龄大于 25 的所有文档
    for document in cursor:
        print(document)
    
  • 指定返回字段
    使用投影来指定返回的字段。如果您只需要某些字段,可以在查询中指定。

    cursor = collection.find({"age": {"$gt": 25}}, {"name": 1, "city": 1, "_id": 0})
    for document in cursor:
        print(document)
    
  • 使用排序和限制结果
    使用 sort() 方法对查询结果进行排序,使用 limit() 方法限制结果数量。

    # 按年龄升序排序,限制结果为前 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 的文档。
    # 查找年龄等于 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() 方法可以将嵌套文档直接插入集合中。

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" 的文档:

query = {"address.city": "New York"}
cursor = collection.find(query)

for document in cursor:
    print(document)

如果文档中包含嵌套文档数组,可以通过点符号和条件组合来查询。例如,查找 addresses 数组中包含 city"San Francisco" 的文档:

query = {"addresses.city": "San Francisco"}
cursor = collection.find(query)

for document in cursor:
    print(document)

更新嵌套文档

通过点符号和 $set 可以更新嵌套文档中的字段。

更新 address.city"Los Angeles" 的操作如下:

collection.update_one(
    {"name": "Alice"},
    {"$set": {"address.city": "Los Angeles"}}
)

通过 $ 操作符可以更新数组中的嵌套字段。如下所示,更新 addresses 数组中 city"San Francisco"zipcode

collection.update_one(
    {"addresses.city": "San Francisco"},
    {"$set": {"addresses.$.zipcode": "94105"}}
)

删除嵌套文档

使用 $unset 可以删除嵌套文档中的字段。

删除 address.zipcode 字段的操作如下:

collection.update_one(
    {"name": "Alice"},
    {"$unset": {"address.zipcode": ""}}
)

通过 $pull 操作符可以从数组中删除特定的嵌套文档。例如,删除 addresses 数组中 city"San Francisco" 的文档:

collection.update_one(
    {"name": "Bob"},
    {"$pull": {"addresses": {"city": "San Francisco"}}}
)

索引操作

索引在 MongoDB 中用于加快查询速度,PyMongo 提供了创建和管理索引的功能。

创建索引

可以为集合中的字段创建索引:

collection.create_index([("name", 1)])  # 1 代表升序索引

列出索引

您可以列出集合中所有的索引:

indexes = collection.list_indexes()
for index in indexes:
    print(index)

删除索引

删除指定的索引:

collection.drop_index("name_1")  # "name_1" 是索引名称

聚合操作

MongoDB 提供了强大的聚合管道操作,用于处理数据的复杂查询和转换。PyMongo 支持 aggregate() 方法来执行聚合查询。

pipeline = [
    {"$match": {"age": {"$gt": 25}}},  # 过滤条件
    {"$group": {"_id": "$city", "average_age": {"$avg": "$age"}}}  # 按照城市分组,计算平均年龄
]
result = collection.aggregate(pipeline)
for doc in result:
    print(doc)

事务支持

对于涉及多个操作的原子性需求,MongoDB 支持事务。在事务中,所有的操作要么成功执行,要么失败回滚。

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

from gridfs import GridFS

fs = GridFS(db)
file_id = fs.put(b"Some large binary data")

下载文件

file_data = fs.get(file_id).read()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值