1PyMongo 3 Migration Guide
2=========================
3
4.. contents::
5
6.. testsetup::
7
8  from pymongo import MongoClient, ReadPreference
9  client = MongoClient()
10  collection = client.my_database.my_collection
11
12PyMongo 3 is a partial rewrite bringing a large number of improvements. It
13also brings a number of backward breaking changes. This guide provides a
14roadmap for migrating an existing application from PyMongo 2.x to 3.x or
15writing libraries that will work with both PyMongo 2.x and 3.x.
16
17PyMongo 2.9
18-----------
19
20The first step in any successful migration involves upgrading to, or
21requiring, at least PyMongo 2.9. If your project has a
22requirements.txt file, add the line "pymongo >= 2.9, < 3.0" until you have
23completely migrated to PyMongo 3. Most of the key new
24methods and options from PyMongo 3.0 are backported in PyMongo 2.9 making
25migration much easier.
26
27Enable Deprecation Warnings
28---------------------------
29
30Starting with PyMongo 2.9, :exc:`DeprecationWarning` is raised by most methods
31removed in PyMongo 3.0. Make sure you enable runtime warnings to see
32where deprecated functions and methods are being used in your application::
33
34  python -Wd <your application>
35
36Warnings can also be changed to errors::
37
38  python -Wd -Werror <your application>
39
40.. note:: Not all deprecated features raise :exc:`DeprecationWarning` when
41  used. For example, the :meth:`~pymongo.collection.Collection.find` options
42  renamed in PyMongo 3.0 do not raise :exc:`DeprecationWarning` when used in
43  PyMongo 2.x. See also `Removed features with no migration path`_.
44
45CRUD API
46--------
47
48Changes to find() and find_one()
49................................
50
51"spec" renamed "filter"
52~~~~~~~~~~~~~~~~~~~~~~~
53
54The `spec` option has been renamed to `filter`. Code like this::
55
56  >>> cursor = collection.find(spec={"a": 1})
57
58can be changed to this with PyMongo 2.9 or later:
59
60.. doctest::
61
62  >>> cursor = collection.find(filter={"a": 1})
63
64or this with any version of PyMongo:
65
66.. doctest::
67
68  >>> cursor = collection.find({"a": 1})
69
70"fields" renamed "projection"
71~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
72
73The `fields` option has been renamed to `projection`. Code like this::
74
75  >>> cursor = collection.find({"a": 1}, fields={"_id": False})
76
77can be changed to this with PyMongo 2.9 or later:
78
79.. doctest::
80
81  >>> cursor = collection.find({"a": 1}, projection={"_id": False})
82
83or this with any version of PyMongo:
84
85.. doctest::
86
87  >>> cursor = collection.find({"a": 1}, {"_id": False})
88
89"partial" renamed "allow_partial_results"
90~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
91
92The `partial` option has been renamed to `allow_partial_results`. Code like
93this::
94
95  >>> cursor = collection.find({"a": 1}, partial=True)
96
97can be changed to this with PyMongo 2.9 or later:
98
99.. doctest::
100
101  >>> cursor = collection.find({"a": 1}, allow_partial_results=True)
102
103"timeout" replaced by "no_cursor_timeout"
104~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
105
106The `timeout` option has been replaced by `no_cursor_timeout`. Code like this::
107
108  >>> cursor = collection.find({"a": 1}, timeout=False)
109
110can be changed to this with PyMongo 2.9 or later:
111
112.. doctest::
113
114  >>> cursor = collection.find({"a": 1}, no_cursor_timeout=True)
115
116"network_timeout" is removed
117~~~~~~~~~~~~~~~~~~~~~~~~~~~~
118
119The `network_timeout` option has been removed. This option was always the
120wrong solution for timing out long running queries and should never be used
121in production. Starting with **MongoDB 2.6** you can use the $maxTimeMS query
122modifier. Code like this::
123
124  # Set a 5 second select() timeout.
125  >>> cursor = collection.find({"a": 1}, network_timeout=5)
126
127can be changed to this with PyMongo 2.9 or later:
128
129.. doctest::
130
131  # Set a 5 second (5000 millisecond) server side query timeout.
132  >>> cursor = collection.find({"a": 1}, modifiers={"$maxTimeMS": 5000})
133
134or with PyMongo 3.5 or later:
135
136  >>> cursor = collection.find({"a": 1}, max_time_ms=5000)
137
138or with any version of PyMongo:
139
140.. doctest::
141
142  >>> cursor = collection.find({"$query": {"a": 1}, "$maxTimeMS": 5000})
143
144.. seealso:: `$maxTimeMS
145  <http://docs.mongodb.org/manual/reference/operator/meta/maxTimeMS/>`_
146
147Tailable cursors
148~~~~~~~~~~~~~~~~
149
150The `tailable` and `await_data` options have been replaced by `cursor_type`.
151Code like this::
152
153  >>> cursor = collection.find({"a": 1}, tailable=True)
154  >>> cursor = collection.find({"a": 1}, tailable=True, await_data=True)
155
156can be changed to this with PyMongo 2.9 or later:
157
158.. doctest::
159
160  >>> from pymongo import CursorType
161  >>> cursor = collection.find({"a": 1}, cursor_type=CursorType.TAILABLE)
162  >>> cursor = collection.find({"a": 1}, cursor_type=CursorType.TAILABLE_AWAIT)
163
164Other removed options
165~~~~~~~~~~~~~~~~~~~~~
166
167The `slave_okay`, `read_preference`, `tag_sets`,
168and `secondary_acceptable_latency_ms` options have been removed. See the `Read
169Preferences`_ section for solutions.
170
171The aggregate method always returns a cursor
172............................................
173
174PyMongo 2.6 added an option to return an iterable cursor from
175:meth:`~pymongo.collection.Collection.aggregate`. In PyMongo 3
176:meth:`~pymongo.collection.Collection.aggregate` always returns a cursor. Use
177the `cursor` option for consistent behavior with PyMongo 2.9 and later:
178
179.. doctest::
180
181  >>> for result in collection.aggregate([], cursor={}):
182  ...     pass
183
184Read Preferences
185----------------
186
187The "slave_okay" option is removed
188..................................
189
190The `slave_okay` option is removed from PyMongo's API. The
191secondaryPreferred read preference provides the same behavior.
192Code like this::
193
194  >>> client = MongoClient(slave_okay=True)
195
196can be changed to this with PyMongo 2.9 or newer:
197
198.. doctest::
199
200  >>> client = MongoClient(readPreference="secondaryPreferred")
201
202The "read_preference" attribute is immutable
203............................................
204
205Code like this::
206
207  >>> from pymongo import ReadPreference
208  >>> db = client.my_database
209  >>> db.read_preference = ReadPreference.SECONDARY
210
211can be changed to this with PyMongo 2.9 or later:
212
213.. doctest::
214
215  >>> db = client.get_database("my_database",
216  ...                          read_preference=ReadPreference.SECONDARY)
217
218Code like this::
219
220  >>> cursor = collection.find({"a": 1},
221  ...                          read_preference=ReadPreference.SECONDARY)
222
223can be changed to this with PyMongo 2.9 or later:
224
225.. doctest::
226
227  >>> coll2 = collection.with_options(read_preference=ReadPreference.SECONDARY)
228  >>> cursor = coll2.find({"a": 1})
229
230.. seealso:: :meth:`~pymongo.database.Database.get_collection`
231
232The "tag_sets" option and attribute are removed
233...............................................
234
235The `tag_sets` MongoClient option is removed. The `read_preference`
236option can be used instead. Code like this::
237
238  >>> client = MongoClient(
239  ...     read_preference=ReadPreference.SECONDARY,
240  ...     tag_sets=[{"dc": "ny"}, {"dc": "sf"}])
241
242can be changed to this with PyMongo 2.9 or later:
243
244.. doctest::
245
246  >>> from pymongo.read_preferences import Secondary
247  >>> client = MongoClient(read_preference=Secondary([{"dc": "ny"}]))
248
249To change the tags sets for a Database or Collection, code like this::
250
251  >>> db = client.my_database
252  >>> db.read_preference = ReadPreference.SECONDARY
253  >>> db.tag_sets = [{"dc": "ny"}]
254
255can be changed to this with PyMongo 2.9 or later:
256
257.. doctest::
258
259  >>> db = client.get_database("my_database",
260  ...                          read_preference=Secondary([{"dc": "ny"}]))
261
262Code like this::
263
264  >>> cursor = collection.find(
265  ...     {"a": 1},
266  ...     read_preference=ReadPreference.SECONDARY,
267  ...     tag_sets=[{"dc": "ny"}])
268
269can be changed to this with PyMongo 2.9 or later:
270
271.. doctest::
272
273  >>> from pymongo.read_preferences import Secondary
274  >>> coll2 = collection.with_options(
275  ...     read_preference=Secondary([{"dc": "ny"}]))
276  >>> cursor = coll2.find({"a": 1})
277
278.. seealso:: :meth:`~pymongo.database.Database.get_collection`
279
280The "secondary_acceptable_latency_ms" option and attribute are removed
281......................................................................
282
283PyMongo 2.x supports `secondary_acceptable_latency_ms` as an option to methods
284throughout the driver, but mongos only supports a global latency option.
285PyMongo 3.x has changed to match the behavior of mongos, allowing migration
286from a single server, to a replica set, to a sharded cluster without a
287surprising change in server selection behavior. A new option,
288`localThresholdMS`, is available through MongoClient and should be used in
289place of `secondaryAcceptableLatencyMS`. Code like this::
290
291  >>> client = MongoClient(readPreference="nearest",
292  ...                      secondaryAcceptableLatencyMS=100)
293
294can be changed to this with PyMongo 2.9 or later:
295
296.. doctest::
297
298  >>> client = MongoClient(readPreference="nearest",
299  ...                      localThresholdMS=100)
300
301Write Concern
302-------------
303
304The "safe" option is removed
305............................
306
307In PyMongo 3 the `safe` option is removed from the entire API.
308:class:`~pymongo.mongo_client.MongoClient` has always defaulted to acknowledged
309write operations and continues to do so in PyMongo 3.
310
311The "write_concern" attribute is immutable
312..........................................
313
314The `write_concern` attribute is immutable in PyMongo 3. Code like this::
315
316  >>> client = MongoClient()
317  >>> client.write_concern = {"w": "majority"}
318
319can be changed to this with any version of PyMongo:
320
321.. doctest::
322
323  >>> client = MongoClient(w="majority")
324
325Code like this::
326
327  >>> db = client.my_database
328  >>> db.write_concern = {"w": "majority"}
329
330can be changed to this with PyMongo 2.9 or later:
331
332.. doctest::
333
334  >>> from pymongo import WriteConcern
335  >>> db = client.get_database("my_database",
336  ...                          write_concern=WriteConcern(w="majority"))
337
338The new CRUD API write methods do not accept write concern options. Code like
339this::
340
341  >>> oid = collection.insert({"a": 2}, w="majority")
342
343can be changed to this with PyMongo 2.9 or later:
344
345.. doctest::
346
347  >>> from pymongo import WriteConcern
348  >>> coll2 = collection.with_options(
349  ...     write_concern=WriteConcern(w="majority"))
350  >>> oid = coll2.insert({"a": 2})
351
352.. seealso:: :meth:`~pymongo.database.Database.get_collection`
353
354Codec Options
355-------------
356
357The "document_class" attribute is removed
358.........................................
359
360Code like this::
361
362  >>> from bson.son import SON
363  >>> client = MongoClient()
364  >>> client.document_class = SON
365
366can be replaced by this in any version of PyMongo:
367
368.. doctest::
369
370  >>> from bson.son import SON
371  >>> client = MongoClient(document_class=SON)
372
373or to change the `document_class` for a :class:`~pymongo.database.Database`
374with PyMongo 2.9 or later:
375
376.. doctest::
377
378  >>> from bson.codec_options import CodecOptions
379  >>> from bson.son import SON
380  >>> db = client.get_database("my_database", CodecOptions(SON))
381
382.. seealso:: :meth:`~pymongo.database.Database.get_collection` and
383  :meth:`~pymongo.collection.Collection.with_options`
384
385The "uuid_subtype" option and attribute are removed
386...................................................
387
388Code like this::
389
390  >>> from bson.binary import JAVA_LEGACY
391  >>> db = client.my_database
392  >>> db.uuid_subtype = JAVA_LEGACY
393
394can be replaced by this with PyMongo 2.9 or later:
395
396.. doctest::
397
398  >>> from bson.binary import JAVA_LEGACY
399  >>> from bson.codec_options import CodecOptions
400  >>> db = client.get_database("my_database",
401  ...                          CodecOptions(uuid_representation=JAVA_LEGACY))
402
403.. seealso:: :meth:`~pymongo.database.Database.get_collection` and
404  :meth:`~pymongo.collection.Collection.with_options`
405
406MongoClient
407-----------
408
409MongoClient connects asynchronously
410...................................
411
412In PyMongo 3, the :class:`~pymongo.mongo_client.MongoClient` constructor no
413longer blocks while connecting to the server or servers, and it no longer
414raises :exc:`~pymongo.errors.ConnectionFailure` if they are unavailable, nor
415:exc:`~pymongo.errors.ConfigurationError` if the user’s credentials are wrong.
416Instead, the constructor returns immediately and launches the connection
417process on background threads. The `connect` option is added to control whether
418these threads are started immediately, or when the client is first used.
419
420For consistent behavior in PyMongo 2.x and PyMongo 3.x, code like this::
421
422  >>> from pymongo.errors import ConnectionFailure
423  >>> try:
424  ...     client = MongoClient()
425  ... except ConnectionFailure:
426  ...     print("Server not available")
427  >>>
428
429can be changed to this with PyMongo 2.9 or later:
430
431.. doctest::
432
433  >>> from pymongo.errors import ConnectionFailure
434  >>> client = MongoClient(connect=False)
435  >>> try:
436  ...     result = client.admin.command("ping")
437  ... except ConnectionFailure:
438  ...     print("Server not available")
439  >>>
440
441Any operation can be used to determine if the server is available. We choose
442the "ping" command here because it is cheap and does not require auth, so
443it is a simple way to check whether the server is available.
444
445The max_pool_size parameter is removed
446......................................
447
448PyMongo 3 replaced the max_pool_size parameter with support for the MongoDB URI
449`maxPoolSize` option. Code like this::
450
451  >>> client = MongoClient(max_pool_size=10)
452
453can be replaced by this with PyMongo 2.9 or later:
454
455.. doctest::
456
457  >>> client = MongoClient(maxPoolSize=10)
458  >>> client = MongoClient("mongodb://localhost:27017/?maxPoolSize=10")
459
460The "disconnect" method is removed
461..................................
462
463Code like this::
464
465  >>> client.disconnect()
466
467can be replaced by this with PyMongo 2.9 or later:
468
469.. doctest::
470
471  >>> client.close()
472
473The host and port attributes are removed
474........................................
475
476Code like this::
477
478  >>> host = client.host
479  >>> port = client.port
480
481can be replaced by this with PyMongo 2.9 or later:
482
483.. doctest::
484
485  >>> address = client.address
486  >>> host, port = address or (None, None)
487
488BSON
489----
490
491"as_class", "tz_aware", and "uuid_subtype" are removed
492......................................................
493
494The `as_class`, `tz_aware`, and `uuid_subtype` parameters have been
495removed from the functions provided in :mod:`bson`. Furthermore, the
496:func:`~bson.encode` and :func:`~bson.decode` functions have been added
497as more performant alternatives to the :meth:`bson.BSON.encode` and
498:meth:`bson.BSON.decode` methods. Code like this::
499
500  >>> from bson import BSON
501  >>> from bson.son import SON
502  >>> encoded = BSON.encode({"a": 1}, as_class=SON)
503
504can be replaced by this in PyMongo 2.9 or later:
505
506.. doctest::
507
508  >>> from bson import encode
509  >>> from bson.codec_options import CodecOptions
510  >>> from bson.son import SON
511  >>> encoded = encode({"a": 1}, codec_options=CodecOptions(SON))
512
513Removed features with no migration path
514---------------------------------------
515
516MasterSlaveConnection is removed
517................................
518
519Master slave deployments are no longer supported by MongoDB. Starting with
520MongoDB 3.0 a replica set can have up to 50 members and that limit is likely
521to be removed in later releases. We recommend migrating to replica sets
522instead.
523
524Requests are removed
525....................
526
527The client methods `start_request`, `in_request`, and `end_request` are
528removed. Requests were designed to make read-your-writes consistency more
529likely with the w=0 write concern. Additionally, a thread in a request used the
530same member for all secondary reads in a replica set. To ensure
531read-your-writes consistency in PyMongo 3.0, do not override the default write
532concern with w=0, and do not override the default read preference of PRIMARY.
533
534The "compile_re" option is removed
535..................................
536
537In PyMongo 3 regular expressions are never compiled to Python match objects.
538
539The "use_greenlets" option is removed
540.....................................
541
542The `use_greenlets` option was meant to allow use of PyMongo with Gevent
543without the use of gevent.monkey.patch_threads(). This option caused a lot
544of confusion and made it difficult to support alternative asyncio libraries
545like Eventlet. Users of Gevent should use gevent.monkey.patch_all() instead.
546
547.. seealso:: :doc:`examples/gevent`
548