Added to the docs, mostly the user guide
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
========
|
||||
Tutorial
|
||||
========
|
||||
This tutorial introduces **MongoEngine** by means of example --- we will walk
|
||||
@@ -10,7 +11,7 @@ focus on the data-modelling side of the application, leaving out a user
|
||||
interface.
|
||||
|
||||
Getting started
|
||||
---------------
|
||||
===============
|
||||
Before we start, make sure that a copy of MongoDB is running in an accessible
|
||||
location --- running it locally will be easier, but if that is not an option
|
||||
then it may be run on a remote server.
|
||||
@@ -27,7 +28,7 @@ database to use::
|
||||
For more information about connecting to MongoDB see :ref:`guide-connecting`.
|
||||
|
||||
Defining our documents
|
||||
----------------------
|
||||
======================
|
||||
MongoDB is *schemaless*, which means that no schema is enforced by the database
|
||||
--- we may add and remove fields however we want and MongoDB won't complain.
|
||||
This makes life a lot easier in many regards, especially when there is a change
|
||||
@@ -46,7 +47,7 @@ specified tag. Finally, it would be nice if **comments** could be added to
|
||||
posts. We'll start with **users**, as the others are slightly more involved.
|
||||
|
||||
Users
|
||||
^^^^^
|
||||
-----
|
||||
Just as if we were using a relational database with an ORM, we need to define
|
||||
which fields a :class:`User` may have, and what their types will be::
|
||||
|
||||
@@ -61,7 +62,7 @@ MongoDB --- this will only be enforced at the application level. Also, the User
|
||||
documents will be stored in a MongoDB *collection* rather than a table.
|
||||
|
||||
Posts, Comments and Tags
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
------------------------
|
||||
Now we'll think about how to store the rest of the information. If we were
|
||||
using a relational database, we would most likely have a table of **posts**, a
|
||||
table of **comments** and a table of **tags**. To associate the comments with
|
||||
@@ -73,7 +74,7 @@ several ways we can achieve this, but each of them have their problems --- none
|
||||
of them stand out as particularly intuitive solutions.
|
||||
|
||||
Posts
|
||||
"""""
|
||||
^^^^^
|
||||
But MongoDB *isn't* a relational database, so we're not going to do it that
|
||||
way. As it turns out, we can use MongoDB's schemaless nature to provide us with
|
||||
a much nicer solution. We will store all of the posts in *one collection* ---
|
||||
@@ -99,12 +100,12 @@ this kind of modelling out of the box::
|
||||
link_url = StringField()
|
||||
|
||||
We are storing a reference to the author of the posts using a
|
||||
:class:`mongoengine.ReferenceField` object. These are similar to foreign key
|
||||
:class:`~mongoengine.ReferenceField` object. These are similar to foreign key
|
||||
fields in traditional ORMs, and are automatically translated into references
|
||||
when they are saved, and dereferenced when they are loaded.
|
||||
|
||||
Tags
|
||||
""""
|
||||
^^^^
|
||||
Now that we have our Post models figured out, how will we attach tags to them?
|
||||
MongoDB allows us to store lists of items natively, so rather than having a
|
||||
link table, we can just store a list of tags in each post. So, for both
|
||||
@@ -120,13 +121,13 @@ size of our database. So let's take a look that the code our modified
|
||||
author = ReferenceField(User)
|
||||
tags = ListField(StringField(max_length=30))
|
||||
|
||||
The :class:`mongoengine.ListField` object that is used to define a Post's tags
|
||||
The :class:`~mongoengine.ListField` object that is used to define a Post's tags
|
||||
takes a field object as its first argument --- this means that you can have
|
||||
lists of any type of field (including lists). Note that we don't need to
|
||||
modify the specialised post types as they all inherit from :class:`Post`.
|
||||
|
||||
Comments
|
||||
""""""""
|
||||
^^^^^^^^
|
||||
A comment is typically associated with *one* post. In a relational database, to
|
||||
display a post with its comments, we would have to retrieve the post from the
|
||||
database, then query the database again for the comments associated with the
|
||||
@@ -152,7 +153,7 @@ We can then store a list of comment documents in our post document::
|
||||
comments = ListField(EmbeddedDocumentField(Comment))
|
||||
|
||||
Adding data to our Tumblelog
|
||||
----------------------------
|
||||
============================
|
||||
Now that we've defined how our documents will be structured, let's start adding
|
||||
some documents to the database. Firstly, we'll need to create a :class:`User`
|
||||
object::
|
||||
@@ -184,10 +185,10 @@ Note that if you change a field on a object that has already been saved, then
|
||||
call :meth:`save` again, the document will be updated.
|
||||
|
||||
Accessing our data
|
||||
------------------
|
||||
==================
|
||||
So now we've got a couple of posts in our database, how do we display them?
|
||||
Each document class (i.e. any class that inherits either directly or indirectly
|
||||
from :class:`mongoengine.Document`) has an :attr:`objects` attribute, which is
|
||||
from :class:`~mongoengine.Document`) has an :attr:`objects` attribute, which is
|
||||
used to access the documents in the database collection associated with that
|
||||
class. So let's see how we can get our posts' titles::
|
||||
|
||||
@@ -195,7 +196,7 @@ class. So let's see how we can get our posts' titles::
|
||||
print post.title
|
||||
|
||||
Retrieving type-specific information
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
------------------------------------
|
||||
This will print the titles of our posts, one on each line. But What if we want
|
||||
to access the type-specific data (link_url, content, etc.)? One way is simply
|
||||
to use the :attr:`objects` attribute of a subclass of :class:`Post`::
|
||||
@@ -205,7 +206,7 @@ to use the :attr:`objects` attribute of a subclass of :class:`Post`::
|
||||
|
||||
Using TextPost's :attr:`objects` attribute only returns documents that were
|
||||
created using :class:`TextPost`. Actually, there is a more general rule here:
|
||||
the :attr:`objects` attribute of any subclass of :class:`mongoengine.Document`
|
||||
the :attr:`objects` attribute of any subclass of :class:`~mongoengine.Document`
|
||||
only looks for documents that were created using that subclass or one of its
|
||||
subclasses.
|
||||
|
||||
@@ -233,20 +234,21 @@ This would print the title of each post, followed by the content if it was a
|
||||
text post, and "Link: <url>" if it was a link post.
|
||||
|
||||
Searching our posts by tag
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
The :attr:`objects` attribute of a :class:`mongoengine.Document` is actually a
|
||||
:class:`mongoengine.QuerySet` object. This lazily queries the database only
|
||||
when you need the data. It may also be filtered to narrow down your query.
|
||||
Let's adjust our query so that only posts with the tag "mongodb" are returned::
|
||||
--------------------------
|
||||
The :attr:`objects` attribute of a :class:`~mongoengine.Document` is actually a
|
||||
:class:`~mongoengine.queryset.QuerySet` object. This lazily queries the
|
||||
database only when you need the data. It may also be filtered to narrow down
|
||||
your query. Let's adjust our query so that only posts with the tag "mongodb"
|
||||
are returned::
|
||||
|
||||
for post in Post.objects(tags='mongodb'):
|
||||
print post.title
|
||||
|
||||
There are also methods available on :class:`mongoengine.QuerySet` objects that
|
||||
allow different results to be returned, for example, calling :meth:`first` on
|
||||
the :attr:`objects` attribute will return a single document, the first matched
|
||||
by the query you provide. Aggregation functions may also be used on
|
||||
:class:`mongoengine.QuerySet` objects::
|
||||
There are also methods available on :class:`~mongoengine.queryset.QuerySet`
|
||||
objects that allow different results to be returned, for example, calling
|
||||
:meth:`first` on the :attr:`objects` attribute will return a single document,
|
||||
the first matched by the query you provide. Aggregation functions may also be
|
||||
used on :class:`~mongoengine.queryset.QuerySet` objects::
|
||||
|
||||
num_posts = Post.objects(tags='mongodb').count()
|
||||
print 'Found % posts with tag "mongodb"' % num_posts
|
||||
|
||||
Reference in New Issue
Block a user