Merge branch 'master' of git://github.com/blackbrrr/mongoengine

_types index prepended to user defined indexes

Conflicts:
	mongoengine/queryset.py
This commit is contained in:
Harry Marr 2010-01-08 06:00:35 +00:00
commit 45080d3fd1
5 changed files with 103 additions and 25 deletions

View File

@ -184,6 +184,41 @@ sign. Note that direction only matters on multi-field indexes. ::
'indexes': ['title', ('title', '-rating')] 'indexes': ['title', ('title', '-rating')]
} }
Ordering
--------
A default ordering can be specified for your :class:`~mongoengine.queryset.QuerySet`
using the :attr:`ordering` attributeof :attr:`~Document.meta`.
Ordering will be applied when the ``QuerySet`` is created, and can be
overridden by subsequent calls to :meth:`~mongoengine.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", published_date=datetime(2010, 1, 5, 0, 0 ,0))
blog_post_2 = BlogPost(title="Blog Post #2", published_date=datetime(2010, 1, 6, 0, 0 ,0))
blog_post_3 = BlogPost(title="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 Document inheritance
-------------------- --------------------
To create a specialised type of a :class:`~mongoengine.Document` you have To create a specialised type of a :class:`~mongoengine.Document` you have

View File

@ -136,6 +136,7 @@ class TopLevelDocumentMetaclass(DocumentMetaclass):
collection = name.lower() collection = name.lower()
simple_class = True simple_class = True
# Subclassed documents inherit collection from superclass # Subclassed documents inherit collection from superclass
for base in bases: for base in bases:
if hasattr(base, '_meta') and 'collection' in base._meta: if hasattr(base, '_meta') and 'collection' in base._meta:
@ -154,6 +155,7 @@ class TopLevelDocumentMetaclass(DocumentMetaclass):
'allow_inheritance': True, 'allow_inheritance': True,
'max_documents': None, 'max_documents': None,
'max_size': None, 'max_size': None,
'ordering': [], # default ordering applied at runtime
'indexes': [] # indexes to be ensured at runtime 'indexes': [] # indexes to be ensured at runtime
} }

View File

@ -19,6 +19,7 @@ class QuerySet(object):
self._document = document self._document = document
self._collection = collection self._collection = collection
self._query = {} self._query = {}
# If inheritance is allowed, only return instances and instances of # If inheritance is allowed, only return instances and instances of
# subclasses of the class being used # subclasses of the class being used
if document._meta.get('allow_inheritance'): if document._meta.get('allow_inheritance'):
@ -29,14 +30,13 @@ class QuerySet(object):
"""Ensure that the given indexes are in place. """Ensure that the given indexes are in place.
""" """
if isinstance(key_or_list, basestring): if isinstance(key_or_list, basestring):
# single-field indexes needn't specify a direction key_or_list = [key_or_list]
if key_or_list.startswith(("-", "+")):
key_or_list = key_or_list[1:]
# Use real field name
key = QuerySet._translate_field_name(self._document, key_or_list)
self._collection.ensure_index(key)
elif isinstance(key_or_list, (list, tuple)):
index_list = [] index_list = []
# If _types is being used, prepend it to every specified index
if self._document._meta.get('allow_inheritance'):
index_list.append(('_types', 1))
for key in key_or_list: for key in key_or_list:
# Get direction from + or - # Get direction from + or -
direction = pymongo.ASCENDING direction = pymongo.ASCENDING
@ -64,7 +64,6 @@ class QuerySet(object):
# Ensure document-defined indexes are created # Ensure document-defined indexes are created
if self._document._meta['indexes']: if self._document._meta['indexes']:
for key_or_list in self._document._meta['indexes']: for key_or_list in self._document._meta['indexes']:
# print "key", key_or_list
self.ensure_index(key_or_list) self.ensure_index(key_or_list)
# If _types is being used (for polymorphism), it needs an index # If _types is being used (for polymorphism), it needs an index
@ -73,6 +72,10 @@ class QuerySet(object):
self._cursor_obj = self._collection.find(self._query) self._cursor_obj = self._collection.find(self._query)
# apply default ordering
if self._document._meta['ordering']:
self.order_by(*self._document._meta['ordering'])
return self._cursor_obj return self._cursor_obj
@classmethod @classmethod
@ -225,6 +228,7 @@ class QuerySet(object):
"""Return an explain plan record for the """Return an explain plan record for the
:class:`~mongoengine.queryset.QuerySet`\ 's cursor. :class:`~mongoengine.queryset.QuerySet`\ 's cursor.
""" """
plan = self._cursor.explain() plan = self._cursor.explain()
if format: if format:
import pprint import pprint

View File

@ -242,9 +242,9 @@ class DocumentTest(unittest.TestCase):
# Indexes are lazy so use list() to perform query # Indexes are lazy so use list() to perform query
list(BlogPost.objects) list(BlogPost.objects)
info = BlogPost.objects._collection.index_information() info = BlogPost.objects._collection.index_information()
self.assertTrue([('category', 1), ('addDate', -1)] in info.values()) self.assertTrue([('_types', 1), ('category', 1), ('addDate', -1)]
# Even though descending order was specified, single-key indexes use 1 in info.values())
self.assertTrue([('addDate', 1)] in info.values()) self.assertTrue([('_types', 1), ('addDate', -1)] in info.values())
BlogPost.drop_collection() BlogPost.drop_collection()

View File

@ -131,6 +131,36 @@ class QuerySetTest(unittest.TestCase):
person = self.Person.objects.with_id(person1.id) person = self.Person.objects.with_id(person1.id)
self.assertEqual(person.name, "User A") self.assertEqual(person.name, "User A")
def test_ordering(self):
"""Ensure default ordering is applied and can be overridden.
"""
from datetime import datetime
class BlogPost(Document):
title = StringField()
published_date = DateTimeField()
meta = {
'ordering': ['-published_date']
}
blog_post_1 = BlogPost(title="Blog Post #1", published_date=datetime(2010, 1, 5, 0, 0 ,0))
blog_post_2 = BlogPost(title="Blog Post #2", published_date=datetime(2010, 1, 6, 0, 0 ,0))
blog_post_3 = BlogPost(title="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")
def test_find_embedded(self): def test_find_embedded(self):
"""Ensure that an embedded document is properly returned from a query. """Ensure that an embedded document is properly returned from a query.
""" """
@ -331,10 +361,17 @@ class QuerySetTest(unittest.TestCase):
"""Ensure that and index is used when '_types' is being used in a """Ensure that and index is used when '_types' is being used in a
query. query.
""" """
class BlogPost(Document):
date = DateTimeField()
meta = {'indexes': ['-date']}
# Indexes are lazy so use list() to perform query # Indexes are lazy so use list() to perform query
list(self.Person.objects) list(BlogPost.objects)
info = self.Person.objects._collection.index_information() info = BlogPost.objects._collection.index_information()
self.assertTrue([('_types', 1)] in info.values()) self.assertTrue([('_types', 1)] in info.values())
self.assertTrue([('_types', 1), ('date', -1)] in info.values())
BlogPost.drop_collection()
class BlogPost(Document): class BlogPost(Document):
title = StringField() title = StringField()