From 5f43c032f2778af7f9c13c32c8cec4e7756569d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20W=C3=B3jcik?= Date: Sun, 26 Feb 2017 21:29:06 -0500 Subject: [PATCH] revamp the "connecting" user guide and test more ways of connecting to a replica set (#1490) --- docs/guide/connecting.rst | 53 +++++++++++++++++++++------------------ docs/guide/installing.rst | 4 +-- tests/test_connection.py | 45 +++++++++++++++++++++++---------- 3 files changed, 62 insertions(+), 40 deletions(-) diff --git a/docs/guide/connecting.rst b/docs/guide/connecting.rst index 827e5a3c..f40ed4c5 100644 --- a/docs/guide/connecting.rst +++ b/docs/guide/connecting.rst @@ -42,13 +42,18 @@ the :attr:`host` to will establish connection to ``production`` database using ``admin`` username and ``qwerty`` password. -ReplicaSets -=========== +Replica Sets +============ -MongoEngine supports -:class:`~pymongo.mongo_replica_set_client.MongoReplicaSetClient`. To use them, -please use an URI style connection and provide the ``replicaSet`` name -in the connection kwargs. +MongoEngine supports connecting to replica sets:: + + from mongoengine import connect + + # Regular connect + connect('dbname', replicaset='rs-name') + + # MongoDB URI-style connect + connect(host='mongodb://localhost/dbname?replicaSet=rs-name') Read preferences are supported through the connection or via individual queries by passing the read_preference :: @@ -59,76 +64,74 @@ queries by passing the read_preference :: Multiple Databases ================== -Multiple database support was added in MongoEngine 0.6. To use multiple -databases you can use :func:`~mongoengine.connect` and provide an `alias` name -for the connection - if no `alias` is provided then "default" is used. +To use multiple databases you can use :func:`~mongoengine.connect` and provide +an `alias` name for the connection - if no `alias` is provided then "default" +is used. In the background this uses :func:`~mongoengine.register_connection` to store the data and you can register all aliases up front if required. Individual documents can also support multiple databases by providing a -`db_alias` in their meta data. This allows :class:`~pymongo.dbref.DBRef` objects -to point across databases and collections. Below is an example schema, using -3 different databases to store data:: +`db_alias` in their meta data. This allows :class:`~pymongo.dbref.DBRef` +objects to point across databases and collections. Below is an example schema, +using 3 different databases to store data:: class User(Document): name = StringField() - meta = {"db_alias": "user-db"} + meta = {'db_alias': 'user-db'} class Book(Document): name = StringField() - meta = {"db_alias": "book-db"} + meta = {'db_alias': 'book-db'} class AuthorBooks(Document): author = ReferenceField(User) book = ReferenceField(Book) - meta = {"db_alias": "users-books-db"} + meta = {'db_alias': 'users-books-db'} Context Managers ================ -Sometimes you may want to switch the database or collection to query against -for a class. +Sometimes you may want to switch the database or collection to query against. For example, archiving older data into a separate database for performance reasons or writing functions that dynamically choose collections to write -document to. +a document to. Switch Database --------------- The :class:`~mongoengine.context_managers.switch_db` context manager allows you to change the database alias for a given class allowing quick and easy -access the same User document across databases:: +access to the same User document across databases:: from mongoengine.context_managers import switch_db class User(Document): name = StringField() - meta = {"db_alias": "user-db"} + meta = {'db_alias': 'user-db'} with switch_db(User, 'archive-user-db') as User: - User(name="Ross").save() # Saves the 'archive-user-db' + User(name='Ross').save() # Saves the 'archive-user-db' Switch Collection ----------------- The :class:`~mongoengine.context_managers.switch_collection` context manager allows you to change the collection for a given class allowing quick and easy -access the same Group document across collection:: +access to the same Group document across collection:: from mongoengine.context_managers import switch_collection class Group(Document): name = StringField() - Group(name="test").save() # Saves in the default db + Group(name='test').save() # Saves in the default db with switch_collection(Group, 'group2000') as Group: - Group(name="hello Group 2000 collection!").save() # Saves in group2000 collection - + Group(name='hello Group 2000 collection!').save() # Saves in group2000 collection .. note:: Make sure any aliases have been registered with diff --git a/docs/guide/installing.rst b/docs/guide/installing.rst index e93f0485..b89d48f0 100644 --- a/docs/guide/installing.rst +++ b/docs/guide/installing.rst @@ -2,13 +2,13 @@ Installing MongoEngine ====================== -To use MongoEngine, you will need to download `MongoDB `_ +To use MongoEngine, you will need to download `MongoDB `_ and ensure it is running in an accessible location. You will also need `PyMongo `_ to use MongoEngine, but if you install MongoEngine using setuptools, then the dependencies will be handled for you. -MongoEngine is available on PyPI, so to use it you can use :program:`pip`: +MongoEngine is available on PyPI, so you can use :program:`pip`: .. code-block:: console diff --git a/tests/test_connection.py b/tests/test_connection.py index d74f68c7..cdcf1377 100644 --- a/tests/test_connection.py +++ b/tests/test_connection.py @@ -198,19 +198,6 @@ class ConnectionTest(unittest.TestCase): self.assertTrue(isinstance(db, pymongo.database.Database)) self.assertEqual(db.name, 'test') - def test_connect_uri_with_replicaset(self): - """Ensure connect() works when specifying a replicaSet.""" - if IS_PYMONGO_3: - c = connect(host='mongodb://localhost/test?replicaSet=local-rs') - db = get_db() - self.assertTrue(isinstance(db, pymongo.database.Database)) - self.assertEqual(db.name, 'test') - else: - # PyMongo < v3.x raises an exception: - # "localhost:27017 is not a member of replica set local-rs" - with self.assertRaises(MongoEngineConnectionError): - c = connect(host='mongodb://localhost/test?replicaSet=local-rs') - def test_uri_without_credentials_doesnt_override_conn_settings(self): """Ensure connect() uses the username & password params if the URI doesn't explicitly specify them. @@ -332,6 +319,38 @@ class ConnectionTest(unittest.TestCase): self.assertEqual(dict(conn1.write_concern), {'w': 1, 'j': True}) self.assertEqual(dict(conn2.write_concern), {'w': 1, 'j': True}) + def test_connect_with_replicaset_via_uri(self): + """Ensure connect() works when specifying a replicaSet via the + MongoDB URI. + """ + if IS_PYMONGO_3: + c = connect(host='mongodb://localhost/test?replicaSet=local-rs') + db = get_db() + self.assertTrue(isinstance(db, pymongo.database.Database)) + self.assertEqual(db.name, 'test') + else: + # PyMongo < v3.x raises an exception: + # "localhost:27017 is not a member of replica set local-rs" + with self.assertRaises(MongoEngineConnectionError): + c = connect(host='mongodb://localhost/test?replicaSet=local-rs') + + def test_connect_with_replicaset_via_kwargs(self): + """Ensure connect() works when specifying a replicaSet via the + connection kwargs + """ + if IS_PYMONGO_3: + c = connect(replicaset='local-rs') + self.assertEqual(c._MongoClient__options.replica_set_name, + 'local-rs') + db = get_db() + self.assertTrue(isinstance(db, pymongo.database.Database)) + self.assertEqual(db.name, 'test') + else: + # PyMongo < v3.x raises an exception: + # "localhost:27017 is not a member of replica set local-rs" + with self.assertRaises(MongoEngineConnectionError): + c = connect(replicaset='local-rs') + def test_datetime(self): connect('mongoenginetest', tz_aware=True) d = datetime.datetime(2010, 5, 5, tzinfo=utc)