Python操作MongoDB看这一篇就够了

目录

MongoDB简介

安装与配置

安装MongoDB

安装Python驱动

基本操作

连接数据库

插入文档

查询文档

更新文档

删除文档

高级操作

索引操作

聚合管道

批量操作

性能优化

实战案例

用户管理系统

日志分析系统

常见问题与解决方案

总结


MongoDB简介

MongoDB是一个基于分布式文件存储的开源NoSQL数据库,由C++语言编写。它采用文档存储格式(BSON,一种类似JSON的二进制存储格式),具有高性能、高可用性和易扩展性等特点。与传统的关系型数据库相比,MongoDB具有以下优势:

  • 无固定表结构,文档格式灵活
  • 水平扩展能力强,适合大数据量存储
  • 支持丰富的查询语言
  • 内置复制和故障转移功能
  • 支持多种编程语言驱动

安装与配置

安装MongoDB

  1. Windows安装

    • 从MongoDB官网下载.msi安装包
    • 运行安装向导,选择"Complete"完整安装
    • 安装完成后,MongoDB默认安装在C:\Program Files\MongoDB目录下
    • 需要手动创建数据存储目录C:\data\db
  2. MacOS安装

    brew tap mongodb/brew
    brew install mongodb-community
    

    启动服务:

    brew services start mongodb-community
    

  3. Linux安装(Ubuntu)

    sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 9DA31620334BD75D9DCB49F368818C72E52529D4
    echo "deb [ arch=amd64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-4.0.list
    sudo apt-get update
    sudo apt-get install -y mongodb-org
    

    启动服务:

    sudo systemctl start mongod
    

安装Python驱动

MongoDB官方提供了Python驱动pymongo

pip install pymongo

如果需要使用更高级的功能,可以安装包含额外工具的pymongo[srv]

pip install pymongo[srv]

基本操作

连接数据库

from pymongo import MongoClient

# 连接本地MongoDB服务
client = MongoClient('mongodb://localhost:27017/')

# 连接远程MongoDB服务
# client = MongoClient('mongodb://username:password@host:port/database')

# 获取或创建数据库
db = client['test_database']

# 获取或创建集合(类似关系型数据库中的表)
collection = db['test_collection']

插入文档

# 插入单个文档
document = {
    "name": "张三",
    "age": 28,
    "skills": ["Python", "MongoDB", "Linux"],
    "address": {
        "city": "北京",
        "street": "朝阳区"
    }
}
insert_result = collection.insert_one(document)
print("插入文档ID:", insert_result.inserted_id)

# 插入多个文档
documents = [
    {"name": "李四", "age": 25, "skills": ["Java", "MySQL"]},
    {"name": "王五", "age": 30, "skills": ["JavaScript", "React"]},
    {"name": "赵六", "age": 22, "skills": ["C++", "Algorithm"]}
]
insert_results = collection.insert_many(documents)
print("插入文档IDs:", insert_results.inserted_ids)

查询文档

# 查询单个文档
document = collection.find_one({"name": "张三"})
print("查询结果:", document)

# 查询多个文档
cursor = collection.find({"age": {"$gt": 25}})  # 查询年龄大于25的文档
for doc in cursor:
    print(doc)

# 高级查询
# $and: 与操作
# $or: 或操作
# $in: 包含
# $lt/$lte/$gt/$gte: 比较操作
# $regex: 正则表达式
cursor = collection.find({
    "$and": [
        {"age": {"$gte": 25}},
        {"skills": {"$in": ["Python"]}}
    ]
})

更新文档

# 更新单个文档
update_result = collection.update_one(
    {"name": "张三"},
    {"$set": {"age": 29, "address.city": "上海"}}
)
print("匹配文档数:", update_result.matched_count)
print("修改文档数:", update_result.modified_count)

# 更新多个文档
update_result = collection.update_many(
    {"age": {"$lt": 30}},
    {"$inc": {"age": 1}}  # 年龄加1
)
print("匹配文档数:", update_result.matched_count)
print("修改文档数:", update_result.modified_count)

删除文档

# 删除单个文档
delete_result = collection.delete_one({"name": "赵六"})
print("删除文档数:", delete_result.deleted_count)

# 删除多个文档
delete_result = collection.delete_many({"age": {"$lt": 25}})
print("删除文档数:", delete_result.deleted_count)

高级操作

索引操作

# 创建索引
collection.create_index([("name", pymongo.ASCENDING)], unique=True)

# 创建复合索引
collection.create_index([("name", pymongo.ASCENDING), ("age", pymongo.DESCENDING)])

# 获取索引信息
indexes = collection.list_indexes()
for index in indexes:
    print(index)

# 删除索引
collection.drop_index("name_1")

聚合管道

pipeline = [
    {"$match": {"age": {"$gt": 25}}},  # 筛选阶段
    {"$group": {"_id": "$address.city", "count": {"$sum": 1}}},  # 分组阶段
    {"$sort": {"count": -1}},  # 排序阶段
    {"$limit": 5}  # 限制阶段
]
results = collection.aggregate(pipeline)
for result in results:
    print(result)

批量操作

from pymongo import UpdateOne, DeleteOne

# 批量写入操作
operations = [
    UpdateOne({"name": "张三"}, {"$set": {"age": 30}}),
    DeleteOne({"name": "李四"}),
    UpdateOne({"name": "王五"}, {"$inc": {"age": 1}}, upsert=True)
]
result = collection.bulk_write(operations)
print("操作结果:", result.bulk_api_result)

性能优化

  1. 合理使用索引

    • 为常用查询字段创建索引
    • 为排序字段创建索引
    • 避免创建过多索引,影响写入性能
  2. 查询优化

    # 使用投影减少返回字段
    collection.find({"age": {"$gt": 25}}, {"name": 1, "age": 1, "_id": 0})
    
    # 限制返回文档数量
    collection.find().limit(10)
    
    # 使用hint强制使用特定索引
    collection.find({"name": "张三"}).hint([("name", 1)])
    

  3. 批量操作

    • 使用insert_many替代多次insert_one
    • 使用bulk_write批量执行更新/删除操作

实战案例

用户管理系统

from datetime import datetime
from pymongo import MongoClient, ASCENDING, DESCENDING

class UserManager:
    def __init__(self, db_name='user_db'):
        self.client = MongoClient('mongodb://localhost:27017/')
        self.db = self.client[db_name]
        self.users = self.db['users']
        # 创建索引
        self.users.create_index([("username", ASCENDING)], unique=True)
        self.users.create_index([("email", ASCENDING)], unique=True)
    
    def add_user(self, username, email, password):
        user = {
            "username": username,
            "email": email,
            "password": password,
            "created_at": datetime.utcnow(),
            "last_login": None,
            "status": "active"
        }
        try:
            result = self.users.insert_one(user)
            return result.inserted_id
        except Exception as e:
            print(f"添加用户失败: {e}")
            return None
    
    def find_user(self, username=None, email=None):
        query = {}
        if username:
            query["username"] = username
        if email:
            query["email"] = email
        return self.users.find_one(query)
    
    def update_user(self, user_id, updates):
        result = self.users.update_one(
            {"_id": user_id},
            {"$set": updates}
        )
        return result.modified_count > 0
    
    def delete_user(self, user_id):
        result = self.users.delete_one({"_id": user_id})
        return result.deleted_count > 0
    
    def list_users(self, page=1, per_page=10):
        skip = (page - 1) * per_page
        cursor = self.users.find().skip(skip).limit(per_page)
        return list(cursor)

# 使用示例
if __name__ == "__main__":
    manager = UserManager()
    # 添加用户
    user_id = manager.add_user("testuser", "test@example.com", "password123")
    # 查询用户
    user = manager.find_user(username="testuser")
    print(user)
    # 更新用户
    manager.update_user(user_id, {"last_login": datetime.utcnow()})
    # 删除用户
    manager.delete_user(user_id)

日志分析系统

class LogAnalyzer:
    def __init__(self, db_name='log_db'):
        self.client = MongoClient('mongodb://localhost:27017/')
        self.db = self.client[db_name]
        self.logs = self.db['logs']
        # 创建TTL索引,日志自动过期
        self.logs.create_index([("timestamp", ASCENDING)], expireAfterSeconds=3600*24*7)  # 7天后自动删除
    
    def log_event(self, level, message, source=None, metadata=None):
        log_entry = {
            "level": level,
            "message": message,
            "source": source,
            "metadata": metadata or {},
            "timestamp": datetime.utcnow()
        }
        return self.logs.insert_one(log_entry).inserted_id
    
    def get_logs(self, level=None, start_time=None, end_time=None, limit=100):
        query = {}
        if level:
            query["level"] = level
        if start_time or end_time:
            query["timestamp"] = {}
            if start_time:
                query["timestamp"]["$gte"] = start_time
            if end_time:
                query["timestamp"]["$lte"] = end_time
        return list(self.logs.find(query).sort("timestamp", DESCENDING).limit(limit))
    
    def analyze_logs(self):
        pipeline = [
            {"$group": {
                "_id": "$level",
                "count": {"$sum": 1},
                "last_time": {"$max": "$timestamp"},
                "first_time": {"$min": "$timestamp"}
            }},
            {"$sort": {"count": -1}}
        ]
        return list(self.logs.aggregate(pipeline))

# 使用示例
if __name__ == "__main__":
    analyzer = LogAnalyzer()
    # 记录日志
    analyzer.log_event("INFO", "Application started", "main.py")
    analyzer.log_event("ERROR", "Failed to connect to database", "db.py", {"retry_count": 3})
    # 查询日志
    logs = analyzer.get_logs(level="ERROR", limit=5)
    print(logs)
    # 分析日志
    stats = analyzer.analyze_logs()
    print(stats)

常见问题与解决方案

  1. 连接失败

    • 检查MongoDB服务是否启动
    • 检查防火墙设置,确保端口27017开放
    • 检查连接字符串是否正确
  2. 性能问题

    • 使用explain()方法分析查询性能
    • 确保查询使用了适当的索引
    • 考虑分片处理大数据集
  3. 内存不足

    • 调整MongoDB的WiredTiger缓存大小
    • 增加服务器内存
    • 优化查询减少内存使用
  4. 数据一致性问题

    • 使用事务(需要MongoDB 4.0+)
    • 合理设计文档结构减少跨文档操作
    • 使用写关注(write concern)确保数据持久化

总结

通过本文,你应该已经掌握了使用Python操作MongoDB的基本方法和高级技巧。MongoDB作为一款流行的NoSQL数据库,在处理非结构化数据、快速开发和水平扩展方面具有明显优势。结合Python的强大生态,可以构建各种高效的数据处理应用。

在实际项目中,建议:

  1. 合理设计文档结构
  2. 为常用查询创建索引
  3. 使用批量操作提高性能
  4. 定期监控数据库性能
  5. 做好数据备份策略

希望这篇指南能帮助你快速上手Python与MongoDB的开发工作!

 

—————————常用命令以及T-SQL增删改查语句————————————–


查看表基本信息:db.getCollection(‘AUDCAD’).stats() 类似于MySql的EXPLAIN

op image.png


倒序查询数据:db.getCollection(‘AUDCAD’).find({}).sort({field:-1})

op image.png


show dbs; #查看全部数据库
show collections; #显示当前数据库中的集合(类似关系数据库中的表)
show users; #查看当前数据库的用户信息
use <db name="">; #切换数据库跟mysql一样
db;或者db.getName(); #查看当前所在数据库
db.help(); #显示数据库操作命令,里面有很多的命令
db.foo.help(); #显示集合操作命令,同样有很多的命令,foo指的是当前数据库下,一个叫foo的集合,并非真正意义上的命令
db.foo.find(); #对于当前数据库中的foo集合进行数据查找(由于没有条件,会列出所有数据)
db.foo.find( { a : 1 } ); #对于当前数据库中的foo集合进行查找,条件是数据中有一个属性叫a,且a的值为1
db.version(); #当前db版本
db.getMongo(); #查看当前db的连接机器地址
db.dropDatabase(); #删除数据库
 

op image.png


增(insert)
1.单条数据插入
db.user.insert({“name”:”jack”,”age”:20})
2.批量数据插入采用命令行for循环
删(remove)
1.不带参数会删除全部数据,且不可恢复,切记!
db.user.remove({“name”:”joe”})
改(update)
1.整体更新
var model = db.user.findOne({“name”:”jack”})
model.age=30
db.user.update({“name”:”jack”},model)
2.局部更新
● inc修改器——比如我们做一个在线用户状态记录,每次修改会在原有的基础上自增𝑖𝑛𝑐修改器——比如我们做一个在线用户状态记录,每次修改会在原有的基础上自增inc指定的值,如果“文档”中没有此key,则会创建key
db.user.update({“name”:”jack”},{inc:{“age”:30}}) //年龄增加30 ●inc:{“age”:30}}) //年龄增加30 ●set修改器
db.user.update({“name”:”jack”},{$set:{“age”:10}}) //年龄变为10</db>

3.upsert操作 —— 如果没有查到,就在数据库里面新增一条,使用起来很简单,将update的第三个参数设为true即可。
4.批量更新 —— 在mongodb中如果匹配多条,默认的情况下只更新第一条,那么如果我们有需求必须批量更新,那么在mongodb中实现也是很简单的,在update的第四个参数中设为true即可
查(find)
1.查找key=value的数据
db.collection.find({ “key” : value })
2.key > value
db.collection.find({ “key” : { [Math Processing Error]gt: value } }) 3.key < value db.collection.find({ “key” : { $lt: value } }) 4.key >= value db.collection.find({ “key” : { $gte: value } }) 5.key <= value db.collection.find({ “key” : { $lte: value } }) 6.value1 < key <value2 db.collection.find({="" "key"="" :="" {="" $gt:="" value1="" ,="" $lt:="" value2="" }="" })="" 7.key="" <=""> value db.collection.find({ “key” : { $ne: value } }) 8.取模运算,条件相当于key % 10 == 1 即key除以10余数为1的 db.collection.find({ “key” : { $mod : [ 10 , 1 ] } }) 9.不属于,条件相当于key的值不属于[ 1, 2, 3 ]中任何一个 db.collection.find({ “key” : { $nin: [ 1, 2, 3 ] } }) 10.属于,条件相当于key等于[ 1, 2, 3 ]中任何一个 db.collection.find({ “key” : { $in: [ 1, 2, 3 ] } }) 11.size 数量、尺寸,条件相当于key的值的数量是1(key必须是数组,一个值的情况不能算是数量为1的数组)
db.collection.find({ “key” : { size: 1 } }) 12.size: 1 } }) 12.exists 字段存在,true返回存在字段key的数据,false返回不存在字度key的数据
db.collection.find({ “key” : { [Math Processing Error]exists : true|false } }) 13.正则,类似like;“i”忽略大小写,“m”支持多行.如joe会匹配出来 db.collection.find({ “name”:/^j/,”name”:/e$/ }) 14.or或 (注意:MongoDB 1.5.3后版本可用),符合条件a=1的或者符合条件b=2的数据都会查询出来
db.collection.find({ [Math Processing Error]or : [{a : 1}, {b : 2} ] }) 15.符合条件key=value ,同时符合其他两个条件中任意一个的数据 db.collection.find({ “key”: value , $or : [{ a : 1 } , { b : 2 }] }) 16.内嵌对象中的值匹配,注意:”key.subkey”必须加引号 db.collection.find({ “key.subkey” :value }) 17.这是一个与其他查询条件组合使用的操作符,不会单独使用。上述查询条件得到的结果集加上not之后就能获得相反的集合。
db.collection.find({ “key”: { not:/val.val𝑛𝑜𝑡:/𝑣𝑎𝑙.𝑣𝑎𝑙/i } })
18.$where中的value,就是我们非常熟悉,非常热爱的js
db.collection.find({ $where:function(){return this.name==”joe”} })</value2>

  • 指定时间删除
    db.getCollection(‘AUDCHF’).remove({“ctm”:{$lt:1534322144}})
  • 设置过期时间(索引)
    db.collection.createIndex({“createdTime”: 1},{expireAfterSeconds: 300})
    其中,dollection表名,expireTime是索引所在的字段,为Date格式,expireAfterSeconds表示0秒之后过期。该方式,可以传入一个过期时间到数据库中,到了指定时间,数据即删除

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

YF云飞

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

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

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

打赏作者

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

抵扣说明:

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

余额充值