Support for sparse indexes and omitting types from indexes

This commit is contained in:
Colin Howe 2011-05-26 19:39:41 +01:00
parent 6f5bd7b0b9
commit 1fa47206aa
2 changed files with 56 additions and 9 deletions

View File

@ -382,15 +382,17 @@ class QuerySet(object):
return self
@classmethod
def _build_index_spec(cls, doc_cls, key_or_list):
def _build_index_spec(cls, doc_cls, spec):
"""Build a PyMongo index spec from a MongoEngine index spec.
"""
if isinstance(key_or_list, basestring):
key_or_list = [key_or_list]
if isinstance(spec, basestring):
spec = {'fields': [spec]}
if isinstance(spec, (list, tuple)):
spec = {'fields': spec}
index_list = []
use_types = doc_cls._meta.get('allow_inheritance', True)
for key in key_or_list:
for key in spec['fields']:
# Get direction from + or -
direction = pymongo.ASCENDING
if key.startswith("-"):
@ -411,10 +413,18 @@ class QuerySet(object):
use_types = False
# If _types is being used, prepend it to every specified index
if doc_cls._meta.get('allow_inheritance') and use_types:
if (spec.get('types', True) and doc_cls._meta.get('allow_inheritance')
and use_types):
index_list.insert(0, ('_types', 1))
return index_list
spec['fields'] = index_list
if spec.get('sparse', False) and len(spec['fields']) > 1:
raise ValueError(
'Sparse indexes can only have one field in them. '
'See https://jira.mongodb.org/browse/SERVER-2193')
return spec
def __call__(self, q_obj=None, class_check=True, **query):
"""Filter the selected documents by calling the
@ -465,9 +475,12 @@ class QuerySet(object):
# Ensure document-defined indexes are created
if self._document._meta['indexes']:
for key_or_list in self._document._meta['indexes']:
self._collection.ensure_index(key_or_list,
background=background, **index_opts)
for spec in self._document._meta['indexes']:
opts = index_opts.copy()
opts['unique'] = spec.get('unique', False)
opts['sparse'] = spec.get('sparse', False)
self._collection.ensure_index(spec['fields'],
background=background, **opts)
# If _types is being used (for polymorphism), it needs an index
if '_types' in self._query:

View File

@ -377,6 +377,40 @@ class DocumentTest(unittest.TestCase):
BlogPost.drop_collection()
def test_dictionary_indexes(self):
"""Ensure that indexes are used when meta[indexes] contains dictionaries
instead of lists.
"""
class BlogPost(Document):
date = DateTimeField(db_field='addDate', default=datetime.now)
category = StringField()
tags = ListField(StringField())
meta = {
'indexes': [
{ 'fields': ['-date'], 'unique': True,
'sparse': True, 'types': False },
],
}
BlogPost.drop_collection()
info = BlogPost.objects._collection.index_information()
# _id, '-date'
self.assertEqual(len(info), 3)
# Indexes are lazy so use list() to perform query
list(BlogPost.objects)
info = BlogPost.objects._collection.index_information()
info = [(value['key'],
value.get('unique', False),
value.get('sparse', False))
for key, value in info.iteritems()]
self.assertTrue(([('addDate', -1)], True, True) in info)
BlogPost.drop_collection()
def test_unique(self):
"""Ensure that uniqueness constraints are applied to fields.
"""