File: differences.rst

package info (click to toggle)
python-motor 3.7.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,572 kB
  • sloc: python: 12,252; javascript: 137; makefile: 74; sh: 8
file content (151 lines) | stat: -rw-r--r-- 4,750 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
.. currentmodule:: motor.motor_tornado

=====================================
Differences between Motor and PyMongo
=====================================

.. warning:: Motor will be deprecated on May 14th, 2026, one year after the production release of the PyMongo Async driver. Critical bug fixes will be made until May 14th, 2027.
  We strongly recommend that Motor users migrate to the PyMongo Async driver while Motor is still supported.
  To learn more, see `the migration guide <https://www.mongodb.com/docs/languages/python/pymongo-driver/current/reference/migration/>`_.

.. important:: This page describes using Motor with Tornado. Beginning in
  version 0.5 Motor can also integrate with asyncio instead of Tornado.

Major differences
=================

Connecting to MongoDB
---------------------

Motor provides a single client class, :class:`MotorClient`. Unlike PyMongo's
:class:`~pymongo.mongo_client.MongoClient`, Motor's client class does
not begin connecting in the background when it is instantiated. Instead it
connects on demand, when you first attempt an operation.

Coroutines
----------

Motor supports nearly every method PyMongo does, but Motor methods that
do network I/O are *coroutines*. See :doc:`tutorial-tornado`.

Threading and forking
---------------------

Multithreading and forking are not supported; Motor is intended to be used in
a single-threaded Tornado application. See Tornado's documentation on
`running Tornado in production`_ to take advantage of multiple cores.

.. _`running Tornado in production`: http://www.tornadoweb.org/en/stable/guide/running.html

Minor differences
=================

.. _gridfs-differences:

GridFS
------

- File-like

    PyMongo's :class:`~gridfs.grid_file.GridIn` and
    :class:`~gridfs.grid_file.GridOut` strive to act like Python's built-in
    file objects, so they can be passed to many functions that expect files.
    But the I/O methods of :class:`MotorGridIn` and
    :class:`MotorGridOut` are asynchronous, so they cannot obey the
    file API and aren't suitable in the same circumstances as files.

- Setting properties

    In PyMongo, you can set arbitrary attributes on
    a :class:`~gridfs.grid_file.GridIn` and they're stored as metadata on
    the server, even after the ``GridIn`` is closed::

        fs = gridfs.GridFSBucket(db)
        grid_in = fs.open_upload_stream('test_file')
        grid_in.close()
        grid_in.my_field = 'my_value'  # Sends update to server.

    Updating metadata on a :class:`MotorGridIn` is asynchronous, so
    the API is different::

        async def f():
            fs = motor.motor_tornado.MotorGridFSBucket(db)
            grid_in = fs.open_upload_stream('test_file')
            await grid_in.close()

            # Sends update to server.
            await grid_in.set('my_field', 'my_value')

.. seealso:: :doc:`../api-tornado/gridfs`.

is_locked
---------

In PyMongo ``is_locked`` is a property of
:class:`~pymongo.mongo_client.MongoClient`. Since determining whether the
server has been fsyncLocked requires I/O, Motor has no such convenience method.
The equivalent in Motor is::

    result = await client.admin.current_op()
    locked = bool(result.get('fsyncLock', None))

system_js
---------

PyMongo supports Javascript procedures stored in MongoDB with syntax like:

.. code-block:: pycon

    >>> db.system_js.my_func = "function(x) { return x * x; }"
    >>> db.system_js.my_func(2)
    4.0

Motor does not.

Cursor slicing
--------------

In PyMongo, the following raises an ``IndexError`` if the collection has fewer
than 101 documents:

.. code-block:: python

    # Can raise IndexError.
    doc = db.collection.find()[100]

In Motor, however, no exception is raised. The query simply has no results:

.. code-block:: python

    async def f():
        cursor = db.collection.find()[100]

        # Iterates zero or one time.
        async for doc in cursor:
            print(doc)

The difference arises because the PyMongo :class:`~pymongo.cursor.Cursor`'s
slicing operator blocks until it has queried the MongoDB server, and determines
if a document exists at the desired offset; Motor simply returns a new
:class:`MotorCursor` with a skip and limit applied.

Creating a collection
---------------------

There are two ways to create a capped collection using PyMongo:

.. code-block:: python

    # Typical:
    db.create_collection("collection1", capped=True, size=1000)

    # Unusual:
    collection = Collection(db, "collection2", capped=True, size=1000)

Motor can't do I/O in a constructor, so the unusual style is prohibited and
only the typical style is allowed:

.. code-block:: python

    async def f():
        await db.create_collection("collection1", capped=True, size=1000)