Support for sparse indexes and omitting types from indexes
This commit is contained in:
parent
6f5bd7b0b9
commit
1fa47206aa
@ -382,15 +382,17 @@ class QuerySet(object):
|
|||||||
return self
|
return self
|
||||||
|
|
||||||
@classmethod
|
@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.
|
"""Build a PyMongo index spec from a MongoEngine index spec.
|
||||||
"""
|
"""
|
||||||
if isinstance(key_or_list, basestring):
|
if isinstance(spec, basestring):
|
||||||
key_or_list = [key_or_list]
|
spec = {'fields': [spec]}
|
||||||
|
if isinstance(spec, (list, tuple)):
|
||||||
|
spec = {'fields': spec}
|
||||||
|
|
||||||
index_list = []
|
index_list = []
|
||||||
use_types = doc_cls._meta.get('allow_inheritance', True)
|
use_types = doc_cls._meta.get('allow_inheritance', True)
|
||||||
for key in key_or_list:
|
for key in spec['fields']:
|
||||||
# Get direction from + or -
|
# Get direction from + or -
|
||||||
direction = pymongo.ASCENDING
|
direction = pymongo.ASCENDING
|
||||||
if key.startswith("-"):
|
if key.startswith("-"):
|
||||||
@ -411,10 +413,18 @@ class QuerySet(object):
|
|||||||
use_types = False
|
use_types = False
|
||||||
|
|
||||||
# If _types is being used, prepend it to every specified index
|
# 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))
|
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):
|
def __call__(self, q_obj=None, class_check=True, **query):
|
||||||
"""Filter the selected documents by calling the
|
"""Filter the selected documents by calling the
|
||||||
@ -465,9 +475,12 @@ 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 spec in self._document._meta['indexes']:
|
||||||
self._collection.ensure_index(key_or_list,
|
opts = index_opts.copy()
|
||||||
background=background, **index_opts)
|
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 is being used (for polymorphism), it needs an index
|
||||||
if '_types' in self._query:
|
if '_types' in self._query:
|
||||||
|
@ -377,6 +377,40 @@ class DocumentTest(unittest.TestCase):
|
|||||||
|
|
||||||
BlogPost.drop_collection()
|
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):
|
def test_unique(self):
|
||||||
"""Ensure that uniqueness constraints are applied to fields.
|
"""Ensure that uniqueness constraints are applied to fields.
|
||||||
"""
|
"""
|
||||||
|
Loading…
x
Reference in New Issue
Block a user