Mongoengine: connect / disconnect questions

Created on 12 Mar 2014  路  4Comments  路  Source: MongoEngine/mongoengine

Hi all -

I have the following code saved in a file called objects.py:

from mongoengine.fields import StringField
from mongoengine.document import Document
from mongoengine.connection import connect, disconnect, get_connection

class ISA(Document):
    SerialNumber = StringField(unique=True,required=True)
    Product = StringField(max_length=50)
    Build = StringField(max_length=50)
    Variant = StringField(max_length=5)

    meta = { 'collection':'ISAData' }

    def __init__(self, sn, product=None, build=None, variant=None):
        super(ISA,self).__init__()
        self.SerialNumber = sn
        self.Product = product
        self.Build = build
        self.Variant = variant

    def __repr__(self):
        return "<SN:{0} PRODUCT:{1} BUILD:{2} VARIANT:{3}>".format(self.SerialNumber, self.Product, self.Build, self.Variant)

I have tried this in both a python2.7 and python3.3 shell:

import objects as mg
mg.connect("test1")
a = ISA('123456').save()
mg.disconnect()
mg.connect("test2")
b = ISA('123456').save()

--->Error on duplicating unique keys

Neither database exisits in MongoDB - the idea is that they are created by the code above, but the connection always points to the first database I connect to, thus the duplication error.

How do I disconnect from 1 database and reconnect to another in the same session?
Did I miss something?

Thanks!

ClienConnect

Most helpful comment

See my issues here: #605, #565, #566.

I've created a work around in the description of #605.
Essentially you need to connect to a first db AND register an alias to it. Unfortunately you can't use aliases only as the docs allude to, there must be an initial 'default' connection (#604), go figure. I just use the first connection in my list.
Then register aliases to all the other DBs as you need them.
Then you use the switch function I created in #605 to force each model to use the updated DB connection via its alias. Due to the design, this is done per-model and not globally so you'll have to call it for each model. Once again, go figure.

I can't figure out the use case for the current design because it certainly doesn't match up with what I would expect and IMO breaks the _principle of least surprise_ in so many places.

The lack of response / fixes is disconcerting. Looking at the API / code / behaviour, I wasn't exactly reassured either.
switch_db is a useless function because it's a context manager method which means it uses enter / exit logic and cannot be maintained outside the with statement.
document.switch_db and document.switch_collection are methods, not classmethods / staticmethods, which means they only work on document instances, not the model class itself, making them only useful for copying individual documents from one db to another. Not exactly a hard thing to replicate via other methods.
disconnect isn't public (it's not exported via __all__, and it's not mentioned in the docs, connect has no publically mentioned / accessible antithesis) and doesn't work even if you forcibly expose it because the models cache the connection and don't check for changes!
connect doesn't re-connect if the parameters are different.

*headdesk*

All 4 comments

Sorry - I am going to close this here and check on the forums first. I am probably using it wrong. If I can't get an answer there or I really have found something, I can re-open it.

My apologies.

Yeah - I can't figure this out. Sorry and thank you.

See my issues here: #605, #565, #566.

I've created a work around in the description of #605.
Essentially you need to connect to a first db AND register an alias to it. Unfortunately you can't use aliases only as the docs allude to, there must be an initial 'default' connection (#604), go figure. I just use the first connection in my list.
Then register aliases to all the other DBs as you need them.
Then you use the switch function I created in #605 to force each model to use the updated DB connection via its alias. Due to the design, this is done per-model and not globally so you'll have to call it for each model. Once again, go figure.

I can't figure out the use case for the current design because it certainly doesn't match up with what I would expect and IMO breaks the _principle of least surprise_ in so many places.

The lack of response / fixes is disconcerting. Looking at the API / code / behaviour, I wasn't exactly reassured either.
switch_db is a useless function because it's a context manager method which means it uses enter / exit logic and cannot be maintained outside the with statement.
document.switch_db and document.switch_collection are methods, not classmethods / staticmethods, which means they only work on document instances, not the model class itself, making them only useful for copying individual documents from one db to another. Not exactly a hard thing to replicate via other methods.
disconnect isn't public (it's not exported via __all__, and it's not mentioned in the docs, connect has no publically mentioned / accessible antithesis) and doesn't work even if you forcibly expose it because the models cache the connection and don't check for changes!
connect doesn't re-connect if the parameters are different.

*headdesk*

I have a very similar issue which I have asked here :
http://stackoverflow.com/questions/43626773/connection-not-getting-created-to-the-new-dbname-in-mongoengine
And haven't really been able to figure out a solution to it so far :(

Was this page helpful?
0 / 5 - 0 ratings