python通过mongoengine中connect函数连接多个数据库
mongoengine支持程序同时连接多个数据库,这些数据库可以位于一个或多个mongo之中,通过alias名称区分不同的连接即可。
可以通过switch_db切换到不同的数据库,进行读写操作,switch_db其实是一个上下文管理器,通过和with语句一起使用,能够保证切换数据库的影响范围。
由于个人电脑上没有安装mongodb,以下代码示例中访问的mongodb通过mongoengine提供的mock mongodb替代,只需要在connect函数参数中加上is_mock=True参数,并且安装有mongomock package(pip install mongomock)即可。
1 #!/usr/bin/env python 2 # coding=utf-8 3 from mongoengine import connect 4 from mongoengine.document import Document 5 from mongoengine.fields import StringField, IntField 6 from mongoengine.context_managers import switch_db 7 8 9 # 连接不同db 10 connect(alias='testdbA', is_mock=True) 11 connect(alias='testdbB', is_mock=True) 12 connect(alias='testdbC', is_mock=True) 13 14 15 class User(Document): 16 meta = { 17 # db_alias用于指定User绑定的mongo连接,和connect函数中的alias对应 18 'db_alias': 'testdbA', 19 } 20 uname = StringField(max_length=63) 21 uid = StringField(max_length=64) 22 age = IntField(default=0) 23 24 25 def create_record(uname, uid, age): 26 user = User() 27 user.uname = uname 28 user.uid = uid 29 user.age = age 30 return user 31 32 def print_records(records): 33 # 输出User类此时绑定的db连接名称,并输出其记录个数 34 records = list(User.objects.all()) 35 print('{} count:{}, records:'.format(User._meta['db_alias'], len(records))) 36 for rc in records: 37 print(' {}|{}|{}'.format(rc['uname'], rc['uid'], rc['age'])) 38 39 40 records = list(User.objects.all()) 41 print_records(records) 42 create_record('Ace', 'AX001', 10).save() 43 print_records(records) 44 45 # switch到testdbB连接 46 with switch_db(User, 'testdbB'): 47 print_records(records) 48 create_record('Bob', 'BX001', 11).save() 49 print_records(records) 50 51 # switch到testdbC连接 52 with switch_db(User, 'testdbC'): 53 print_records(records) 54 create_record('Carl', 'CX001', 12).save() 55 print_records(records)
运行结果如下:
$ python mongo_test.py testdbA count:0, records: testdbA count:1, records: Ace|AX001|10 testdbB count:0, records: testdbB count:1, records: Bob|BX001|11 testdbC count:0, records: testdbC count:1, records: Carl|CX001|12
switch_db其实就是一个简单的上下文管理器,源码位于mongoengine/context_managers.py当中,其实就是在switch_db对象初始化时、进入with代码块前、离开with代码块后,通过改变db_alias和collection两个字段对应的取值,实现了不同mongodb连接的切换,代码简单注释版本如下:
1 class switch_db(object): 2 """switch_db alias context manager. 3 4 Example :: 5 6 # Register connections 7 register_connection('default', 'mongoenginetest') 8 register_connection('testdb-1', 'mongoenginetest2') 9 10 class Group(Document): 11 name = StringField() 12 13 Group(name='test').save() # Saves in the default db 14 15 with switch_db(Group, 'testdb-1') as Group: 16 Group(name='hello testdb!').save() # Saves in testdb-1 17 """ 18 19 def __init__(self, cls, db_alias): 20 """Construct the switch_db context manager 21 22 :param cls: the class to change the registered db 23 :param db_alias: the name of the specific database to use 24 """ 25 self.cls = cls 26 # 存储切换前的collection 27 self.collection = cls._get_collection() 28 # 设置为要切换的db连接名称 29 self.db_alias = db_alias 30 # 存储切换前的原db连接名称 31 self.ori_db_alias = cls._meta.get('db_alias', DEFAULT_CONNECTION_NAME) 32 def __enter__(self): 33 """Change the db_alias and clear the cached collection.""" 34 # 进入with代码块前触发 35 # 修改为本次指定的db连接名称 36 self.cls._meta['db_alias'] = self.db_alias 37 # 将collection置为None,于是之后会重新根据新的db连接获取collection 38 self.cls._collection = None 39 return self.cls 40 41 def __exit__(self, t, value, traceback): 42 """Reset the db_alias and collection.""" 43 # 退出with代码块后触发 44 # 恢复为切换前的db连接名称 45 self.cls._meta['db_alias'] = self.ori_db_alias 46 # 恢复为切换前的collection 47 self.cls._collection = self.collection
签名:拥抱开源,拥抱自由
分类:
python
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端