@@ -13,17 +13,14 @@ marrow.mongo
13
13
..
14
14
15
15
16
-
17
-
18
- Introduction
19
- ============
20
-
21
16
Marrow Mongo is a collection of small, focused utilities written to enhance use of the `PyMongo native MongoDB driver
22
17
<http://api.mongodb.com/python/current/> `__ without the overhead, glacial update cycle, complexity, and head-space
23
18
requirements of a full active record object document mapper. Additionally, it provides a very light-weight database
24
19
connection plugin for the `WebCore web framework <https://github.com/marrow/WebCore >`__ and Python standard logging
25
20
adapter to emit logs to MongoDB.
26
21
22
+ Additional documentation is provided in the form of an `online reference manual <https://mongo.webcore.io/ >`__.
23
+
27
24
28
25
Installation
29
26
============
@@ -49,166 +46,8 @@ This package has a few dependencies:
49
46
* A modern (>3.2) version of the ``pymongo `` package.
50
47
* The Marrow Package and Schema utility packages for plugin handling and declarative syntax support.
51
48
52
- There are a few conditional, tag-based dependencies:
53
-
54
- * ``development `` installs additional utilites relating to testing and contribution.
55
- * ``scripting `` pulls in the `Javascripthon <https://github.com/azazel75/metapensiero.pj >`__ Python to JavaScript
56
- transpiler to enable use of native Python function transport to MongoDB. (E.g. for use in map/reduce, stored
57
- functions, etc.)
58
- * ``logger `` requires knowledge of the local host's timezone, so pulls in ``tzlocal `` to retrieve this information.
59
-
60
- Installing ``marrow.mongo `` will also install package dependencies automatically. To utilize optional tags, add them,
61
- comma separated, beween square braces. E.g. ``marrow.mongo[scripting,logger] ``. On a command line this will require
62
- quoting.
63
-
64
-
65
- Development Version
66
- -------------------
67
-
68
- |developstatus | |developcover | |develophealth | |ghsince | |issuecount | |ghfork |
69
-
70
- Development takes place on `GitHub <https://github.com/ >`__ in the
71
- `marrow.mongo <https://github.com/marrow/mongo/ >`__ project. Issue tracking, documentation, and downloads
72
- are provided there.
73
-
74
- Installing the current development version requires `Git <http://git-scm.com/ >`__, a distributed source code management
75
- system. If you have Git you can run the following to download and *link * the development version into your Python
76
- runtime::
77
-
78
- git clone https://github.com/marrow/mongo.git
79
- (cd mongo; python setup.py develop)
80
-
81
- You can then upgrade to the latest version at any time::
82
-
83
- (cd mongo; git pull; python setup.py develop)
84
-
85
- If you would like to make changes and contribute them back to the project, fork the GitHub project, make your changes,
86
- and submit a pull request. This process is beyond the scope of this documentation; for more information see
87
- `GitHub's documentation <http://help.github.com/ >`__.
88
-
89
-
90
- Documents
91
- =========
92
-
93
- This package utilizes the `Marrow Schema <https://github.com/marrow/schema >`__ declarative schema toolkit and extends
94
- it to encompass MongoDB data storage concerns. You define data models by importing classes describing the various
95
- components of a collection, such as ``Document ``, ``ObjectId ``, or ``String ``, then compose them into a declarative
96
- class model. For example, if you wanted to define a simple user account model, you would begin by importing::
97
-
98
- from marrow.mongo import Index, Document
99
- from marrow.mongo.field import ObjectId, String, Number, Array
100
-
101
- Defining Documents
102
- ------------------
103
-
104
- Now we can define our own ``Document `` subclass::
105
-
106
- class Account(Document):
107
- username = String(required=True)
108
- name = String()
109
- locale = String(default='en-CA-u-tz-cator-cu-CAD', assign=True)
110
- age = Number()
111
-
112
- id = ObjectId('_id', assign=True)
113
- tag = Array(String(), default=lambda: [], assign=True)
114
-
115
- _username = Index('username', unique=True)
116
-
117
- Broken down::
118
-
119
- class Account(Document):
120
-
121
- No surprises here, we subclass the Document class. This is required to utilize the metaclass that makes the
122
- declarative naming and order-presrving sequence generation work. We begin to define fields::
123
-
124
- username = String(required=True)
125
- name = String()
126
- locale = String(default='en-CA-u-tz-cator-cu-CAD', assign=True)
127
-
128
- Introduced here is ``required ``, indicating that when generating the *validation document * for this document to
129
- ensure this field always has a value. This validation is not currently performed application-side. Also notable is the
130
- use of ``assign `` on a string field; this will assign the default value during instantiation. Then we have a different
131
- type of field::
132
-
133
- age = Number()
134
-
135
- This allows storage of any numeric value, either integer or floating point. Now there is the record identifier::
136
-
137
- id = ObjectId('_id', assign=True)
138
-
139
- Marrow Mongo does not assume your documents contain IDs; there is no separation internally between top-level documents
140
- and "embedded documents", leaving the declaration of an ID up to you. You might not always wish to use an ObjectID,
141
- either; please see MongoDB's documentation for discussion of general modelling practices. The first positional
142
- parameter for most non-complex fields is the name of the MongoDB-side field. Underscores imply an attribute is
143
- "protected" in Python, so we remap it by assigning it to just ``id ``. The ``assign `` argument here ensures whenever a
144
- new ``Account `` is instantiated an ObjectID will be immediately generated and assigned.
145
-
146
- Finally there is an array of tags::
147
-
148
- tag = Array(String(), default=lambda: [], assign=True)
149
-
150
- This combines what we've been using so far into one field. An ``Array `` is a *complex field * (a container) and as such
151
- the types of values allowed to be contained therein may be defined positionally. (If you want to override the field's
152
- database-side name, pass in a ``name `` as a keyword argument.) A default is defined as an anonymous callback function
153
- which constructs a new list on each request. The default will be executed and the result assigned automatically during
154
- initialization as per ``id `` or ``locale ``.
155
-
156
- Lastly we define a unique index on the username to speed up any queries involving that field::
157
-
158
- _username = Index('username', unique=True)
159
-
160
-
161
- Instantiating Documents
162
- -----------------------
163
-
164
- With a document schema defined we can now begin populating data::
165
-
166
- alice = Account('amcgregor', "Alice Bevan-McGregor", age=27)
167
- print(alice.id) # Already has an ID.
168
- print(alice.id.generation_time) # This even includes the creation time.
169
-
170
- As can be seen above construction accepts positional and keyword parameters. Fields will be filled, positionally, in
171
- the order they were defined, unless otherwise adjusted using the ``adjust_attribute_sequence `` decorator.
172
-
173
- Assuming a ``pymongo `` collection is accessible by the variable name ``collection `` we can construct our index::
174
-
175
- Account._username.create_index(collection)
176
-
177
- There is no need to run this command more than once unless the collection is dropped.
178
-
179
- Let's insert our record::
180
-
181
- result = collection.insert_one(alice)
182
- assert result.acknowledged and result.inserted_id == alice.id
183
-
184
- Yup, that's it. Instances of ``Document `` are directly usable in place of a dictionary argument to ``pymongo ``
185
- methods. We then validate that the document we wanted inserted was, in fact, inserted. Using an assert in this way,
186
- this validation will not be run in production code run with the ``-O `` option passed (or ``PYTHONOPTIMIZE ``
187
- environment variable set) in the invocation to Python.
188
-
189
-
190
- Querying Documents
191
- ------------------
192
-
193
- Now that we have a document stored in the database, let's retrieve it back out and get the result as an ``Account ``
194
- instance::
195
-
196
- record = collection.find_one(Account.username == 'amcgregor')
197
- record = Account.from_mongo(record)
198
- print(record.name) # Alice Bevan-McGregor
199
-
200
- Several things are going on here. First it's important to note that Marrow Mongo isn't making the query happen for
201
- you, and does not automatically cast dictionaries to ``Document `` subclasses when querying. The first line
202
- demonstrates the native approach to building *filter documents *, the first argument to ``find `` or ``find_one ``.
203
-
204
- You can use standard Python comparison operators, bitwise operators, and several additional querying methods through
205
- class-level access to the defined fields. The result of one of these operations or method calls is a dictionary-like
206
- object that is the query. They may be combined through bitwise and (``& ``) and bitwise or (``| ``) operations, however
207
- due to Python's order of operations, individual field comparisons must be wrapped in parenthesis if combining.
208
-
209
- Combining produces a new ``Ops `` instance, so it is possible to use these to pre-construct parts of queries prior to
210
- use. As a tip, it can save time (and visual clutter) to assign the document class to a short, single-character
211
- variable name to make repeated reference easier.
49
+ Additional instructions on `conditional dependencies, package flags, and development version utilization
50
+ <https://mongo.webcore.io/installation.html> `__ are available in the manual.
212
51
213
52
214
53
Version History
@@ -281,12 +120,12 @@ OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
281
120
:target: https://github.com/marrow/mongo/issues
282
121
:alt: Github Issues
283
122
284
- .. |ghsince | image :: https://img.shields.io/github/commits-since/marrow/mongo/1.1.0 .svg
123
+ .. |ghsince | image :: https://img.shields.io/github/commits-since/marrow/mongo/1.1.1 .svg
285
124
:target: https://github.com/marrow/mongo/commits/develop
286
125
:alt: Changes since last release.
287
126
288
127
.. |ghtag | image :: https://img.shields.io/github/tag/marrow/mongo.svg
289
- :target: https://github.com/marrow/mongo/tree/1.1.0
128
+ :target: https://github.com/marrow/mongo/tree/1.1.1
290
129
:alt: Latest Github tagged release.
291
130
292
131
.. |latestversion | image :: http://img.shields.io/pypi/v/marrow.mongo.svg?style=flat
0 commit comments