6
6
Welcome to nanomongo's documentation!
7
7
=====================================
8
8
9
- **nanomongo ** is a minimal MongoDB Object-Document Mapper for Python.
10
- It does not attempt to be a feature-complete ODM but if you like
11
- using ``pymongo `` api with python dictionaries and often find yourself
12
- writing validators and ``pymongo.Collection `` wrappers, nanomongo
13
- might suit your needs.
9
+ **nanomongo ** is a minimal MongoDB Object-Document Mapper for Python. It does not attempt to be a feature-complete
10
+ ODM but if you enjoy using `PyMongo <https://api.mongodb.com/python/current >`_ API with dictionaries and often find yourself writing validators and
11
+ ``pymongo.Collection `` wrappers, nanomongo might suit your needs.
14
12
15
- nanomongo has full test coverage.
16
-
17
- **Quick Links **: `Source (github) <https://github.com/eguven/nanomongo >`_ - `Documentation (rtd) <https://nanomongo.readthedocs.org/ >`_ - `Packages (PyPi) <https://pypi.python.org/pypi/nanomongo/ >`_
18
-
19
- **Version 0.4 **: Utility methods `dbref_field_getters `_, :meth: `~.document.BaseDocument.get_dbref `
20
- and Bugfix `Python23 text type compatibility <https://github.com/eguven/nanomongo/pull/14 >`_
21
-
22
- **Version 0.3 **: nanomongo is now python2 compatible (with syntactic difference
23
- when defining your Document, see `Defining Your Document `_ below).
13
+ **Quick Links **: `Source (github) <https://github.com/eguven/nanomongo >`_ - `Documentation (rtd) <https://nanomongo.readthedocs.org/ >`_ - `Packages (PyPi) <https://pypi.python.org/pypi/nanomongo/ >`_ - `Changelog <https://github.com/eguven/nanomongo/blob/master/CHANGELOG.md >`_
24
14
25
15
Installation
26
16
------------
@@ -29,84 +19,74 @@ Installation
29
19
30
20
$ pip install nanomongo
31
21
32
- Quick Tutorial
22
+ Quickstart
33
23
--------------
34
24
35
- Defining Your Document
36
- ^^^^^^^^^^^^^^^^^^^^^^
25
+ Defining A Document And Registering
26
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
37
27
38
- ::
28
+ You can define a document as shown below ::
39
29
40
30
import pymongo
41
- from nanomongo import Index, Field, BaseDocument
42
-
43
- mclient = pymongo.MongoClient()
31
+ from nanomongo import Field, BaseDocument
44
32
45
- class Py23CompatibleDoc(BaseDocument):
46
- client = mclient
47
- db = 'dbname'
48
- dot_notation = True
49
- foo = Field(str)
50
- bar = Field(int, required=False)
51
33
52
- # Python3 only
53
- class Py3Doc(BaseDocument, dot_notation= True, client=mclient, db='dbname'):
34
+ class Py23Doc(BaseDocument):
35
+ dot_notation = True # to allow attribute-like access to document keys
54
36
foo = Field(str)
55
37
bar = Field(int, required=False)
56
38
57
39
__indexes__ = [
58
- Index ('foo'),
59
- Index ([('bar', 1), ('foo', -1)], unique=True),
40
+ pymongo.IndexModel ('foo'),
41
+ pymongo.IndexModel ([('bar', 1), ('foo', -1)], unique=True),
60
42
]
61
43
62
- You don't have to declare `` client `` or `` db `` as shown above, you can
63
- :meth: ` ~.document.BaseDocument.register ` (and I definitely prefer it on
64
- python2) your document later as such:
44
+ # before use, the document needs to be registered. The following will connect
45
+ # to the database and create indexes if necessary
46
+ Py23Doc.register(client=pymongo.MongoClient(), db='mydbname', collection='Py23Doc')
65
47
66
- ::
48
+ Python3 allows slightly cleaner definitions ::
67
49
68
- client = pymongo.MongoClient()
69
- MyDoc.register(client=client, db='dbname', collection='mydoc')
50
+ # Python3 only
51
+ class MyDoc(BaseDocument, dot_notation=True):
52
+ foo = Field(str)
53
+ bar = Field(int, required=False)
70
54
71
- If you omit ``collection `` when defining/registering your document,
72
- `` __name__.lower() `` will be used by default
55
+ If you omit ``collection `` when defining/registering your document, `` __name__.lower() `` will
56
+ be used by default.
73
57
74
- Creating, Inserting, Saving
75
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^
58
+ Creating, Inserting, Querying, Saving
59
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
76
60
::
77
61
78
- doc = MyDoc(foo='42') # or MyDoc({'foo': '42'})
79
- doc.bar = 42 # attribute style access because dot_notation=True
80
- doc.insert()
81
-
82
- :meth: `~.document.BaseDocument.insert() ` is a wrapper around
83
- ``pymongo.Collection().insert() `` and has the same return value (``_id ``)
84
- unless you explicitly set ``w=0 `` ::
85
-
86
- doc.foo = 'new foo' # this change is recorded
87
- del doc.bar # this is recored as well
88
- doc.save() # save only does partial updates
89
-
90
- :meth: `~.document.BaseDocument.save() ` uses ``pymongo.Collection().update() ``
91
- with the changed data. The above will run ::
62
+ doc = MyDoc(foo='1337', bar=42) # creates document {'foo': '1337', 'bar': 42}
63
+ doc.insert() # returns pymongo.results.InsertOneResult
64
+ MyDoc.find_one({'foo': '1337'}) # returns document {'_id': ObjectId('...'), 'bar': 42, 'foo': '1337'}
92
65
93
- update({'_id': doc['_id']}, {'$set': {'foo': 'new foo'}, '$unset': {'bar': 1}})
66
+ doc.foo = '42' # records the change
67
+ del doc.bar # records the change
68
+ # save only does partial updates, this will call
69
+ # collection.update_one({'_id': doc['_id']}, {'$set': {'foo': '42'}, '$unset': {'bar': 1}})
70
+ doc.save() # returns pymongo.results.UpdateResult
94
71
95
- Querying
96
- ^^^^^^^^
97
- ::
72
+ MyDoc.find_one({'foo': '1337'}) # returns None
73
+ MyDoc.find_one({'foo': '42'}) # returns document {'_id': ObjectId('...'), 'foo': '42'}
98
74
99
- Doc.find({'bar': 42})
100
- Doc.find_one({'foo': 'new foo'})
75
+ :meth: `~.document.BaseDocument.insert() ` is a wrapper around
76
+ ``pymongo.Collection.insert_one() `` and :meth: `~.document.BaseDocument.save() ` is
77
+ a wrapper around ``pymongo.Collection.update_one() ``. They pass along received
78
+ keyword arguments and have the same return value.
101
79
102
80
:meth: `~.document.BaseDocument.find() ` and :meth: `~.document.BaseDocument.find_one() `
103
- methods are essentially wrappers around respective methods of ``pymongo.Collection() ``
104
- and they take the same arguments .
81
+ methods are wrappers around respective methods of ``pymongo.Collection `` with same
82
+ arguments and return values .
105
83
106
84
Extensive Example
107
85
-----------------
108
86
109
- See :doc: `example `
87
+ .. toctree ::
88
+ example
89
+
110
90
111
91
Advanced Features
112
92
-----------------
@@ -122,14 +102,17 @@ on your document instance and record the change to be applied later when
122
102
123
103
::
124
104
125
- # lets expand our MyDoc
126
- class NewDoc(MyDoc):
105
+ import pymongo
106
+ from nanomongo import Field, BaseDocument
107
+
108
+ class NewDoc(BaseDocument, dot_notation=True):
127
109
list_field = Field(list)
128
110
dict_field = Field(dict)
129
111
130
- NewDoc.register(client=client , db='dbname ')
131
- doc_id = NewDoc(list_field=[42], dict_field={'foo':[]}).insert()
112
+ NewDoc.register(client=pymongo.MongoClient() , db='mydbname ')
113
+ doc_id = NewDoc(list_field=[42], dict_field={'foo':[]}).insert().inserted_id
132
114
doc = NewDoc.find_one({'_id': doc_id})
115
+ # {'_id': ObjectId('...'), 'dict_field': {'foo': []}, 'list_field': [42]}
133
116
134
117
doc.addToSet('list_field', 1337)
135
118
doc.addToSet('dict_field.foo', 'like a boss')
@@ -141,12 +124,17 @@ Both of the above ``addToSet`` are applied to the ``NewDoc`` instance like Mongo
141
124
- add new value to list field if it's missing (append)
142
125
- complain if it is not a list field
143
126
144
- When save is called, query becomes: ::
127
+ When save is called, the following is called::
128
+
129
+ update_one(
130
+ {'_id': doc['_id']},
131
+ {'$addToSet': {'list_field': {'$each': [1337]}}, 'dict_field.foo': {'$each': ['like a boss']}}
132
+ )
145
133
146
- update({'$addToSet': {'list_field': {'$each': [1337]}},
147
- 'dict_field.foo': {'$each': ['like a boss']}})
134
+ Undefined fields or field type mismatch raises :class: `~.errors.ValidationError `::
148
135
149
- Undefined fields or field type mismatch raises :class: `~.errors.ValidationError `.
136
+ doc.addToSet('dict_field.foo', 'like a boss')
137
+ ValidationError: Cannot apply $addToSet modifier to non-array: dict_field=<class 'dict'>
150
138
151
139
QuerySpec check
152
140
^^^^^^^^^^^^^^^
@@ -162,13 +150,13 @@ an experimental feature at the moment and only does type checks as such:
162
150
163
151
or ``{'foo.bar': 1} `` will log warnings if
164
152
165
- - ``foo `` field is not of type ``dict `` or ``list `` (dotted field type)
153
+ - ``foo `` field is not of type ``dict `` or ``list ``
166
154
167
155
dbref_field_getters
168
- -------------------
156
+ ^^^^^^^^^^^^^^^^^^^
169
157
170
158
Documents that define ``bson.DBRef `` fields automatically generate getter methods
171
- through :func: `nanomongo .document.ref_getter_maker ` where the generated methods
159
+ through :func: `~ .document.ref_getter_maker ` where the generated methods
172
160
have names such as ``get_<field_name>_field ``.
173
161
::
174
162
@@ -182,13 +170,16 @@ have names such as ``get_<field_name>_field``.
182
170
user = Field(DBRef)
183
171
184
172
nanomongo tries to guess the ``document_class `` if it's not provided by looking at
185
- registered subclasses of :class: `~.document.BaseDocument `. If it matches two (for example
186
- when two document classes use the same collection), it will raise
173
+ registered subclasses of :class: `~.document.BaseDocument `. If it matches more than one
174
+ (for example when two document classes use the same collection), it will raise
187
175
:class: `~.errors.UnsupportedOperation `.
188
176
189
177
pymongo & motor
190
178
---------------
191
179
180
+ **0.5.0 update **: motor support is currently not in a working state, this section is
181
+ kept for reference.
182
+
192
183
Throughout the documentation, ``pymongo `` is referenced but all features work the
193
184
same when using `motor <https://github.com/mongodb/motor >`_ transparently if you
194
185
register the document class with a ``motor.MotorClient ``.
@@ -221,10 +212,10 @@ Contents
221
212
.. toctree ::
222
213
:titlesonly:
223
214
224
- field
225
215
document
226
- util
227
216
errors
217
+ field
218
+ util
228
219
229
220
230
221
Indices and tables
0 commit comments