Support for sparse indexes and omitting types from indexes
This commit is contained in:
		| @@ -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: | ||||
|   | ||||
| @@ -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. | ||||
|         """ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user