PyMongo 3 Migration Guide

    PyMongo 3 is a partial rewrite bringing a large number of improvements. It also brings a number of backward breaking changes. This guide provides a roadmap for migrating an existing application from PyMongo 2.x to 3.x or writing libraries that will work with both PyMongo 2.x and 3.x.

    The first step in any successful migration involves upgrading to, or requiring, at least PyMongo 2.9. If your project has a requirements.txt file, add the line “pymongo >= 2.9, < 3.0” until you have completely migrated to PyMongo 3. Most of the key new methods and options from PyMongo 3.0 are backported in PyMongo 2.9 making migration much easier.

    Starting with PyMongo 2.9, DeprecationWarning is raised by most methods removed in PyMongo 3.0. Make sure you enable runtime warnings to see where deprecated functions and methods are being used in your application:

    Warnings can also be changed to errors:

    Note

    Not all deprecated features raise when used. For example, the find() options renamed in PyMongo 3.0 do not raise when used in PyMongo 2.x. See also Removed features with no migration path.

    CRUD API

    “spec” renamed “filter”

    The spec option has been renamed to filter. Code like this:

    1. >>> cursor = collection.find(spec={"a": 1})

    can be changed to this with PyMongo 2.9 or later:

    1. >>> cursor = collection.find(filter={"a": 1})

    or this with any version of PyMongo:

    1. >>> cursor = collection.find({"a": 1})

    “fields” renamed “projection”

    The fields option has been renamed to projection. Code like this:

    1. >>> cursor = collection.find({"a": 1}, fields={"_id": False})

    can be changed to this with PyMongo 2.9 or later:

    1. >>> cursor = collection.find({"a": 1}, projection={"_id": False})

    or this with any version of PyMongo:

    1. >>> cursor = collection.find({"a": 1}, {"_id": False})

    “partial” renamed “allow_partial_results”

    The partial option has been renamed to allow_partial_results. Code like this:

    1. >>> cursor = collection.find({"a": 1}, partial=True)

    can be changed to this with PyMongo 2.9 or later:

    1. >>> cursor = collection.find({"a": 1}, allow_partial_results=True)

    “timeout” replaced by “no_cursor_timeout”

    The timeout option has been replaced by no_cursor_timeout. Code like this:

    1. >>> cursor = collection.find({"a": 1}, timeout=False)

    can be changed to this with PyMongo 2.9 or later:

    1. >>> cursor = collection.find({"a": 1}, no_cursor_timeout=True)

    “network_timeout” is removed

    The network_timeout option has been removed. This option was always the wrong solution for timing out long running queries and should never be used in production. Starting with MongoDB 2.6 you can use the $maxTimeMS query modifier. Code like this:

    1. # Set a 5 second select() timeout.
    2. >>> cursor = collection.find({"a": 1}, network_timeout=5)

    can be changed to this with PyMongo 2.9 or later:

    1. # Set a 5 second (5000 millisecond) server side query timeout.
    2. >>> cursor = collection.find({"a": 1}, modifiers={"$maxTimeMS": 5000})

    or with PyMongo 3.5 or later:

    1. >>> cursor = collection.find({"a": 1}, max_time_ms=5000)

    or with any version of PyMongo:

    1. >>> cursor = collection.find({"$query": {"a": 1}, "$maxTimeMS": 5000})

    See also

    The tailable and await_data options have been replaced by cursor_type. Code like this:

    1. >>> cursor = collection.find({"a": 1}, tailable=True)
    2. >>> cursor = collection.find({"a": 1}, tailable=True, await_data=True)

    can be changed to this with PyMongo 2.9 or later:

    1. >>> from pymongo import CursorType
    2. >>> cursor = collection.find({"a": 1}, cursor_type=CursorType.TAILABLE)
    3. >>> cursor = collection.find({"a": 1}, cursor_type=CursorType.TAILABLE_AWAIT)

    The slave_okay, read_preference, tag_sets, and secondary_acceptable_latency_ms options have been removed. See the Read Preferences section for solutions.

    The aggregate method always returns a cursor

    PyMongo 2.6 added an option to return an iterable cursor from . In PyMongo 3 aggregate() always returns a cursor. Use the cursor option for consistent behavior with PyMongo 2.9 and later:

    The “slave_okay” option is removed

    1. >>> client = MongoClient(slave_okay=True)

    can be changed to this with PyMongo 2.9 or newer:

    1. >>> client = MongoClient(readPreference="secondaryPreferred")

    The “read_preference” attribute is immutable

    Code like this:

    1. >>> from pymongo import ReadPreference
    2. >>> db = client.my_database
    3. >>> db.read_preference = ReadPreference.SECONDARY

    can be changed to this with PyMongo 2.9 or later:

    1. >>> db = client.get_database("my_database",
    2. ... read_preference=ReadPreference.SECONDARY)

    Code like this:

    1. >>> cursor = collection.find({"a": 1},
    2. ... read_preference=ReadPreference.SECONDARY)

    can be changed to this with PyMongo 2.9 or later:

    1. >>> coll2 = collection.with_options(read_preference=ReadPreference.SECONDARY)
    2. >>> cursor = coll2.find({"a": 1})

    See also

    The tag_sets MongoClient option is removed. The read_preference option can be used instead. Code like this:

    1. >>> client = MongoClient(
    2. ... read_preference=ReadPreference.SECONDARY,
    3. ... tag_sets=[{"dc": "ny"}, {"dc": "sf"}])

    can be changed to this with PyMongo 2.9 or later:

    1. >>> client = MongoClient(read_preference=Secondary([{"dc": "ny"}]))

    To change the tags sets for a Database or Collection, code like this:

    1. >>> db = client.my_database
    2. >>> db.read_preference = ReadPreference.SECONDARY
    3. >>> db.tag_sets = [{"dc": "ny"}]

    can be changed to this with PyMongo 2.9 or later:

    1. >>> db = client.get_database("my_database",
    2. ... read_preference=Secondary([{"dc": "ny"}]))

    Code like this:

    1. >>> cursor = collection.find(
    2. ... {"a": 1},
    3. ... read_preference=ReadPreference.SECONDARY,
    4. ... tag_sets=[{"dc": "ny"}])

    can be changed to this with PyMongo 2.9 or later:

    1. >>> from pymongo.read_preferences import Secondary
    2. ... read_preference=Secondary([{"dc": "ny"}]))
    3. >>> cursor = coll2.find({"a": 1})

    See also

    get_collection()

    The “secondary_acceptable_latency_ms” option and attribute are removed

    PyMongo 2.x supports secondary_acceptable_latency_ms as an option to methods throughout the driver, but mongos only supports a global latency option. PyMongo 3.x has changed to match the behavior of mongos, allowing migration from a single server, to a replica set, to a sharded cluster without a surprising change in server selection behavior. A new option, localThresholdMS, is available through MongoClient and should be used in place of secondaryAcceptableLatencyMS. Code like this:

    1. >>> client = MongoClient(readPreference="nearest",
    2. ... secondaryAcceptableLatencyMS=100)

    can be changed to this with PyMongo 2.9 or later:

    1. >>> client = MongoClient(readPreference="nearest",
    2. ... localThresholdMS=100)

    Write Concern

    In PyMongo 3 the safe option is removed from the entire API. has always defaulted to acknowledged write operations and continues to do so in PyMongo 3.

    The write_concern attribute is immutable in PyMongo 3. Code like this:

    1. >>> client = MongoClient()
    2. >>> client.write_concern = {"w": "majority"}

    can be changed to this with any version of PyMongo:

    1. >>> client = MongoClient(w="majority")

    Code like this:

    1. >>> db = client.my_database
    2. >>> db.write_concern = {"w": "majority"}

    can be changed to this with PyMongo 2.9 or later:

    The new CRUD API write methods do not accept write concern options. Code like this:

    1. >>> oid = collection.insert({"a": 2}, w="majority")

    can be changed to this with PyMongo 2.9 or later:

    1. >>> from pymongo import WriteConcern
    2. >>> coll2 = collection.with_options(
    3. ... write_concern=WriteConcern(w="majority"))
    4. >>> oid = coll2.insert({"a": 2})

    See also

    get_collection()

    Codec Options

    The “document_class” attribute is removed

    1. >>> from bson.son import SON
    2. >>> client = MongoClient()
    3. >>> client.document_class = SON

    can be replaced by this in any version of PyMongo:

    1. >>> from bson.son import SON
    2. >>> client = MongoClient(document_class=SON)

    or to change the document_class for a with PyMongo 2.9 or later:

    1. >>> from bson.codec_options import CodecOptions
    2. >>> from bson.son import SON

    See also

    get_collection() and

    Code like this:

    1. >>> from bson.binary import JAVA_LEGACY
    2. >>> db = client.my_database
    3. >>> db.uuid_subtype = JAVA_LEGACY

    can be replaced by this with PyMongo 2.9 or later:

    1. >>> from bson.binary import JAVA_LEGACY
    2. >>> from bson.codec_options import CodecOptions
    3. >>> db = client.get_database("my_database",
    4. ... CodecOptions(uuid_representation=JAVA_LEGACY))

    See also

    get_collection() and

    In PyMongo 3, the MongoClient constructor no longer blocks while connecting to the server or servers, and it no longer raises if they are unavailable, nor ConfigurationError if the user’s credentials are wrong. Instead, the constructor returns immediately and launches the connection process on background threads. The connect option is added to control whether these threads are started immediately, or when the client is first used.

    For consistent behavior in PyMongo 2.x and PyMongo 3.x, code like this:

    1. >>> from pymongo.errors import ConnectionFailure
    2. >>> try:
    3. ... client = MongoClient()
    4. ... except ConnectionFailure:
    5. ... print("Server not available")
    6. >>>

    can be changed to this with PyMongo 2.9 or later:

    1. >>> from pymongo.errors import ConnectionFailure
    2. >>> client = MongoClient(connect=False)
    3. >>> try:
    4. ... result = client.admin.command("ping")
    5. ... except ConnectionFailure:
    6. ... print("Server not available")
    7. >>>

    Any operation can be used to determine if the server is available. We choose the “ping” command here because it is cheap and does not require auth, so it is a simple way to check whether the server is available.

    The max_pool_size parameter is removed

    PyMongo 3 replaced the max_pool_size parameter with support for the MongoDB URI maxPoolSize option. Code like this:

    1. >>> client = MongoClient(max_pool_size=10)

    can be replaced by this with PyMongo 2.9 or later:

    1. >>> client = MongoClient(maxPoolSize=10)
    2. >>> client = MongoClient("mongodb://localhost:27017/?maxPoolSize=10")

    Code like this:

    1. >>> client.disconnect()

    can be replaced by this with PyMongo 2.9 or later:

    1. >>> client.close()

    The host and port attributes are removed

    Code like this:

    1. >>> host = client.host
    2. >>> port = client.port

    can be replaced by this with PyMongo 2.9 or later:

    1. >>> address = client.address
    2. >>> host, port = address or (None, None)

    BSON

    “as_class”, “tz_aware”, and “uuid_subtype” are removed

    The as_class, tz_aware, and uuid_subtype parameters have been removed from the functions provided in . Furthermore, the encode() and functions have been added as more performant alternatives to the bson.BSON.encode() and methods. Code like this:

    1. >>> from bson import BSON
    2. >>> from bson.son import SON
    3. >>> encoded = BSON.encode({"a": 1}, as_class=SON)

    can be replaced by this in PyMongo 2.9 or later:

    1. >>> from bson import encode
    2. >>> from bson.codec_options import CodecOptions
    3. >>> from bson.son import SON

    Master slave deployments are no longer supported by MongoDB. Starting with MongoDB 3.0 a replica set can have up to 50 members and that limit is likely to be removed in later releases. We recommend migrating to replica sets instead.

    The client methods start_request, in_request, and end_request are removed. Requests were designed to make read-your-writes consistency more likely with the w=0 write concern. Additionally, a thread in a request used the same member for all secondary reads in a replica set. To ensure read-your-writes consistency in PyMongo 3.0, do not override the default write concern with w=0, and do not override the default read preference of PRIMARY.

    In PyMongo 3 regular expressions are never compiled to Python match objects.

    The use_greenlets option was meant to allow use of PyMongo with Gevent without the use of gevent.monkey.patch_threads(). This option caused a lot of confusion and made it difficult to support alternative asyncio libraries like Eventlet. Users of Gevent should use gevent.monkey.patch_all() instead.

    See also

    Gevent