Moved sections from user guide to separate pages
This commit is contained in:
		
							
								
								
									
										238
									
								
								docs/guide/defining-documents.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										238
									
								
								docs/guide/defining-documents.rst
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,238 @@ | ||||
| ================== | ||||
| Defining documents | ||||
| ================== | ||||
| In MongoDB, a **document** is roughly equivalent to a **row** in an RDBMS. When | ||||
| working with relational databases, rows are stored in **tables**, which have a | ||||
| strict **schema** that the rows follow. MongoDB stores documents in | ||||
| **collections** rather than tables - the principle difference is that no schema  | ||||
| is enforced at a database level.  | ||||
|  | ||||
| Defining a document's schema | ||||
| ============================ | ||||
| MongoEngine allows you to define schemata for documents as this helps to reduce | ||||
| coding errors, and allows for utility methods to be defined on fields which may | ||||
| be present.  | ||||
|  | ||||
| To define a schema for a document, create a class that inherits from | ||||
| :class:`~mongoengine.Document`. Fields are specified by adding **field | ||||
| objects** as class attributes to the document class:: | ||||
|  | ||||
|     from mongoengine import * | ||||
|     import datetime | ||||
|      | ||||
|     class Page(Document): | ||||
|         title = StringField(max_length=200, required=True) | ||||
|         date_modified = DateTimeField(default=datetime.now) | ||||
|  | ||||
| Fields | ||||
| ====== | ||||
| By default, fields are not required. To make a field mandatory, set the | ||||
| :attr:`required` keyword argument of a field to ``True``. Fields also may have | ||||
| validation constraints available (such as :attr:`max_length` in the example | ||||
| above). Fields may also take default values, which will be used if a value is | ||||
| not provided. Default values may optionally be a callable, which will be called | ||||
| to retrieve the value (such as in the above example). The field types available  | ||||
| are as follows: | ||||
|  | ||||
| * :class:`~mongoengine.StringField` | ||||
| * :class:`~mongoengine.IntField` | ||||
| * :class:`~mongoengine.FloatField` | ||||
| * :class:`~mongoengine.DateTimeField` | ||||
| * :class:`~mongoengine.ListField` | ||||
| * :class:`~mongoengine.ObjectIdField` | ||||
| * :class:`~mongoengine.EmbeddedDocumentField` | ||||
| * :class:`~mongoengine.ReferenceField` | ||||
|  | ||||
| List fields | ||||
| ^^^^^^^^^^^ | ||||
| MongoDB allows the storage of lists of items. To add a list of items to a | ||||
| :class:`~mongoengine.Document`, use the :class:`~mongoengine.ListField` field | ||||
| type. :class:`~mongoengine.ListField` takes another field object as its first | ||||
| argument, which specifies which type elements may be stored within the list:: | ||||
|  | ||||
|     class Page(Document): | ||||
|         tags = ListField(StringField(max_length=50)) | ||||
|  | ||||
| Embedded documents | ||||
| ^^^^^^^^^^^^^^^^^^ | ||||
| MongoDB has the ability to embed documents within other documents. Schemata may | ||||
| be defined for these embedded documents, just as they may be for regular | ||||
| documents. To create an embedded document, just define a document as usual, but | ||||
| inherit from :class:`~mongoengine.EmbeddedDocument` rather than  | ||||
| :class:`~mongoengine.Document`:: | ||||
|  | ||||
|     class Comment(EmbeddedDocument): | ||||
|         content = StringField() | ||||
|  | ||||
| To embed the document within another document, use the | ||||
| :class:`~mongoengine.EmbeddedDocumentField` field type, providing the embedded | ||||
| document class as the first argument:: | ||||
|  | ||||
|     class Page(Document): | ||||
|         comments = ListField(EmbeddedDocumentField(Comment)) | ||||
|  | ||||
|     comment1 = Comment('Good work!') | ||||
|     comment2 = Comment('Nice article!') | ||||
|     page = Page(comments=[comment1, comment2]) | ||||
|  | ||||
| Reference fields | ||||
| ^^^^^^^^^^^^^^^^ | ||||
| References may be stored to other documents in the database using the | ||||
| :class:`~mongoengine.ReferenceField`. Pass in another document class as the | ||||
| first argument to the constructor, then simply assign document objects to the | ||||
| field:: | ||||
|      | ||||
|     class User(Document): | ||||
|         name = StringField() | ||||
|  | ||||
|     class Page(Document): | ||||
|         content = StringField() | ||||
|         author = ReferenceField(User) | ||||
|  | ||||
|     john = User(name="John Smith") | ||||
|     john.save() | ||||
|  | ||||
|     post = Page(content="Test Page") | ||||
|     post.author = john | ||||
|     post.save() | ||||
|  | ||||
| The :class:`User` object is automatically turned into a reference behind the | ||||
| scenes, and dereferenced when the :class:`Page` object is retrieved. | ||||
|  | ||||
| Uniqueness constraints | ||||
| ^^^^^^^^^^^^^^^^^^^^^^ | ||||
| MongoEngine allows you to specify that a field should be unique across a | ||||
| collection by providing ``unique=True`` to a :class:`~mongoengine.Field`\ 's | ||||
| constructor. If you try to save a document that has the same value for a unique | ||||
| field as a document that is already in the database, a  | ||||
| :class:`~mongoengine.OperationError` will be raised. You may also specify | ||||
| multi-field uniqueness constraints by using :attr:`unique_with`, which may be | ||||
| either a single field name, or a list or tuple of field names:: | ||||
|  | ||||
|     class User(Document): | ||||
|         username = StringField(unique=True) | ||||
|         first_name = StringField() | ||||
|         last_name = StringField(unique_with='last_name') | ||||
|  | ||||
| Document collections | ||||
| ==================== | ||||
| Document classes that inherit **directly** from :class:`~mongoengine.Document` | ||||
| will have their own **collection** in the database. The name of the collection | ||||
| is by default the name of the class, coverted to lowercase (so in the example | ||||
| above, the collection would be called `page`). If you need to change the name | ||||
| of the collection (e.g. to use MongoEngine with an existing database), then | ||||
| create a class dictionary attribute called :attr:`meta` on your document, and | ||||
| set :attr:`collection` to the name of the collection that you want your | ||||
| document class to use:: | ||||
|  | ||||
|     class Page(Document): | ||||
|         title = StringField(max_length=200, required=True) | ||||
|         meta = {'collection': 'cmsPage'} | ||||
|  | ||||
| Capped collections | ||||
| ^^^^^^^^^^^^^^^^^^ | ||||
| A :class:`~mongoengine.Document` may use a **Capped Collection** by specifying | ||||
| :attr:`max_documents` and :attr:`max_size` in the :attr:`meta` dictionary. | ||||
| :attr:`max_documents` is the maximum number of documents that is allowed to be | ||||
| stored in the collection, and :attr:`max_size` is the maximum size of the | ||||
| collection in bytes. If :attr:`max_size` is not specified and | ||||
| :attr:`max_documents` is, :attr:`max_size` defaults to 10000000 bytes (10MB). | ||||
| The following example shows a :class:`Log` document that will be limited to  | ||||
| 1000 entries and 2MB of disk space:: | ||||
|  | ||||
|     class Log(Document): | ||||
|         ip_address = StringField() | ||||
|         meta = {'max_documents': 1000, 'max_size': 2000000} | ||||
|  | ||||
| Indexes | ||||
| ======= | ||||
| You can specify indexes on collections to make querying faster. This is done | ||||
| by creating a list of index specifications called :attr:`indexes` in the | ||||
| :attr:`~mongoengine.Document.meta` dictionary, where an index specification may | ||||
| either be a single field name, or a tuple containing multiple field names. A | ||||
| direction may be specified on fields by prefixing the field name with a **+** | ||||
| or a **-** sign. Note that direction only matters on multi-field indexes. :: | ||||
|  | ||||
|     class Page(Document): | ||||
|         title = StringField() | ||||
|         rating = StringField() | ||||
|         meta = { | ||||
|             'indexes': ['title', ('title', '-rating')] | ||||
|         } | ||||
|          | ||||
| Ordering | ||||
| ======== | ||||
| A default ordering can be specified for your | ||||
| :class:`~mongoengine.queryset.QuerySet` using the :attr:`ordering` attribute of | ||||
| :attr:`~mongoengine.Document.meta`.  Ordering will be applied when the | ||||
| :class:`~mongoengine.queryset.QuerySet` is created, and can be overridden by | ||||
| subsequent calls to :meth:`~mongoengine.queryset.QuerySet.order_by`. :: | ||||
|  | ||||
|     from datetime import datetime | ||||
|  | ||||
|     class BlogPost(Document): | ||||
|         title = StringField() | ||||
|         published_date = DateTimeField() | ||||
|  | ||||
|         meta = { | ||||
|             'ordering': ['-published_date'] | ||||
|         } | ||||
|  | ||||
|     blog_post_1 = BlogPost(title="Blog Post #1") | ||||
|     blog_post_1.published_date = datetime(2010, 1, 5, 0, 0 ,0)) | ||||
|  | ||||
|     blog_post_2 = BlogPost(title="Blog Post #2")  | ||||
|     blog_post_2.published_date = datetime(2010, 1, 6, 0, 0 ,0)) | ||||
|  | ||||
|     blog_post_3 = BlogPost(title="Blog Post #3") | ||||
|     blog_post_3.published_date = datetime(2010, 1, 7, 0, 0 ,0)) | ||||
|  | ||||
|     blog_post_1.save() | ||||
|     blog_post_2.save() | ||||
|     blog_post_3.save() | ||||
|  | ||||
|     # get the "first" BlogPost using default ordering | ||||
|     # from BlogPost.meta.ordering | ||||
|     latest_post = BlogPost.objects.first()  | ||||
|     self.assertEqual(latest_post.title, "Blog Post #3") | ||||
|  | ||||
|     # override default ordering, order BlogPosts by "published_date" | ||||
|     first_post = BlogPost.objects.order_by("+published_date").first() | ||||
|     self.assertEqual(first_post.title, "Blog Post #1") | ||||
|  | ||||
| Document inheritance | ||||
| ==================== | ||||
| To create a specialised type of a :class:`~mongoengine.Document` you have | ||||
| defined, you may subclass it and add any extra fields or methods you may need. | ||||
| As this is new class is not a direct subclass of | ||||
| :class:`~mongoengine.Document`, it will not be stored in its own collection; it | ||||
| will use the same collection as its superclass uses. This allows for more | ||||
| convenient and efficient retrieval of related documents:: | ||||
|  | ||||
|     # Stored in a collection named 'page' | ||||
|     class Page(Document): | ||||
|         title = StringField(max_length=200, required=True) | ||||
|  | ||||
|     # Also stored in the collection named 'page' | ||||
|     class DatedPage(Page): | ||||
|         date = DateTimeField() | ||||
|  | ||||
| Working with existing data | ||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||||
| To enable correct retrieval of documents involved in this kind of heirarchy, | ||||
| two extra attributes are stored on each document in the database: :attr:`_cls` | ||||
| and :attr:`_types`. These are hidden from the user through the MongoEngine | ||||
| interface, but may not be present if you are trying to use MongoEngine with  | ||||
| an existing database. For this reason, you may disable this inheritance | ||||
| mechansim, removing the dependency of :attr:`_cls` and :attr:`_types`, enabling | ||||
| you to work with existing databases. To disable inheritance on a document | ||||
| class, set :attr:`allow_inheritance` to ``False`` in the :attr:`meta` | ||||
| dictionary:: | ||||
|  | ||||
|     # Will work with data in an existing collection named 'cmsPage' | ||||
|     class Page(Document): | ||||
|         title = StringField(max_length=200, required=True) | ||||
|         meta = { | ||||
|             'collection': 'cmsPage', | ||||
|             'allow_inheritance': False, | ||||
|         } | ||||
		Reference in New Issue
	
	Block a user