未在 mongoengine 中创建与新 dbname 的连接
Posted
技术标签:
【中文标题】未在 mongoengine 中创建与新 dbname 的连接【英文标题】:connection not getting created to the new dbname in mongoengine 【发布时间】:2017-09-23 10:02:30 【问题描述】:我正在尝试使用 python Mongoengine 创建数据库并将文档添加到不同的数据库。以下是我的尝试:
from mongoengine import *
class MongoDataAccessObject():
# method to connect to the database and initialize the tables etc.
def __init__(self, my_env, helperObj):
print "initializing db for the environment ", my_env
self.con = None
self.dbName = my_env
self.helper_obj = helperObj
try:
self.con = connect(db=self.dbName)
except Exception as e:
print e
def addRecord(self, document_object):
document_object.save()
现在,我在创建上述类的对象时传递我想要创建的不同数据库的名称,并像这样添加文档:
for my_env in list_of_envs:
dao = MongoDataAccessObject(my_env, helper_object)
dao.addRecord(myDocument)
现在这里有两个问题:
-
出于某种原因,我的所有文档都不断添加到同一个数据库中(第一个在创建 MongoDataAccessObject 对象时传递。我假设每次创建新对象时,每次都传递不同的数据库名称,应该为传递的新数据库创建一个新连接,并且应该将文档添加到当前连接到的数据库中。
为了验证我是否真正连接到有问题的数据库,我在连接对象上找不到像 get_database_name() 这样的方法。有没有办法验证我是否连接到正在传递的数据库名称?
好的,做了更多的研究,发现了这个: https://github.com/MongoEngine/mongoengine/issues/605
在 iptyhon 中这样尝试:
from mongoengine import *
import datetime
class Page(Document):
title = StringField(max_length=200, required=True)
date_modified = DateTimeField(default=datetime.datetime.now)
def switch(model, db):
model._meta['db_alias'] = db
# must set _collection to none so it is re-evaluated
model._collection = None
return model
register_connection('default', name='testing')
register_connection('mycon', name='db1')
page = Page(title="Test Page")
page = switch(page, 'mycon')
page.save()
这可以工作并创建一个名为 db1 的数据库并将文档存储在那里。
现在我再次这样做:
register_connection('mycon2', name='db2')
page = Page(title="Test Page")
page = switch(page, 'mycon2')
page.save()
与我的预期相反,这次没有创建 db2(从 mongo 客户端和 Robomongo 检查),但是文档已成功保存。想知道当时文档到底保存在哪里??
所以要弄清楚重复上述练习,并进行如下小改动:
register_connection('mycon2', name='db2')
page = Page(title="Test Page")
page = switch(page, 'mycon2')
x = page.save()
# did a dir(x) and found that there is _get_db, so tried it out as below
x._get_db()
输出是:
数据库(MongoClient(host=['localhost:27017'], document_class=dict, tz_aware=False, connect=True, read_preference=Primary()), u'db2')
我猜这意味着该文档已保存在名为 db2 的数据库中。但是这个 db2 到底在哪里????为什么我不能通过 mongo 客户端甚至 Robomongo 等看到它?
【问题讨论】:
【参考方案1】:最后,我能找到实现上述目标的唯一方法是通过 MongoEngine 提供的上下文管理器 with 语句,这里也有很好的记录:http://docs.mongoengine.org/guide/connecting.html#switch-database
我在上面的代码中的做法是这样的:
在第一次调用 db 时,需要创建一个默认的 db,它应该具有默认的别名。只有这样才能创建另一个别名,否则 Mongoengine 会抛出一个错误,说没有找到默认的 db。
为此,当创建第一个 db 对象时,会向 MongoDataAccessObject 的 __init__ 发送一个 False 标志 因此,为此,MongoDataAccessObject 也被更改为这样的:
class MongoDataAccessObject():
# method to connect to the database and initialize the tables etc.
def __init__(self, my_env, helperObj, is_default_db_set):
print "initializing db for the environment ", my_env
self.con = None
self.dbName = my_env
self.helper_obj = helperObj
self.db_alias = my_env
self.is_default_db_set = is_default_db_set
try:
# all of this part with the is_default_db_set and register_connection() is needed because MongoEngine does not
# provide a simple way of changing dbs or switching db connections. The only way to do it is through the switch_db()
# context manager they provide (which has been used in the addRecord() below)
if not self.is_default_db_set:
self.con = connect(db=self.dbName, alias='default')
else:
# register_connection(alias_name, db_name)
register_connection(self.db_alias, self.dbName)
except Exception as e:
print e
而addRecord()也被修改为:
def addRecord(self, document_object):
with switch_db(model_object, self.db_alias) as model_object:
document_object = model_object()
document_object.save()
上面的这部分:
for my_env in list_of_envs:
dao = MongoDataAccessObject(my_env, helper_object)
dao.addRecord(myDocument)
也被修改为:
for my_env in list_of_envs:
dao = MongoDataAccessObject(my_env,helper_object,mongo_default_db_flag)
dao.addRecord(myDocument)
这似乎对我有用。
【讨论】:
以上是关于未在 mongoengine 中创建与新 dbname 的连接的主要内容,如果未能解决你的问题,请参考以下文章
如何在 MySQL/MariaDB 中创建与 root 具有相同权限的用户? [关闭]