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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM