Add new meta option to Document: allow_index_creation.
Defaults to True. If set to False then MongoEngine will not ensure indexes exist
This commit is contained in:
		| @@ -74,6 +74,11 @@ class Document(BaseDocument): | |||||||
|     names. Index direction may be specified by prefixing the field names with |     names. Index direction may be specified by prefixing the field names with | ||||||
|     a **+** or **-** sign. |     a **+** or **-** sign. | ||||||
|  |  | ||||||
|  |     Index creation can be disabled by specifying :attr:`index_allow_creation` in | ||||||
|  |     the :attr:`meta` dictionary. If this is set to True then indexes will not be | ||||||
|  |     created by MongoEngine. This is useful in production systems where index | ||||||
|  |     creation is performed as part of a deployment system. | ||||||
|  |  | ||||||
|     By default, _types will be added to the start of every index (that |     By default, _types will be added to the start of every index (that | ||||||
|     doesn't contain a list) if allow_inheritence is True. This can be |     doesn't contain a list) if allow_inheritence is True. This can be | ||||||
|     disabled by either setting types to False on the specific index or |     disabled by either setting types to False on the specific index or | ||||||
|   | |||||||
| @@ -481,13 +481,60 @@ class QuerySet(object): | |||||||
|         """Returns all documents.""" |         """Returns all documents.""" | ||||||
|         return self.__call__() |         return self.__call__() | ||||||
|  |  | ||||||
|  |     def _ensure_indexes_exist(self): | ||||||
|  |         background = self._document._meta.get('index_background', False) | ||||||
|  |         drop_dups = self._document._meta.get('index_drop_dups', False) | ||||||
|  |         index_opts = self._document._meta.get('index_options', {}) | ||||||
|  |         index_types = self._document._meta.get('index_types', True) | ||||||
|  |  | ||||||
|  |         # determine if an index which we are creating includes | ||||||
|  |         # _type as its first field; if so, we can avoid creating | ||||||
|  |         # an extra index on _type, as mongodb will use the existing | ||||||
|  |         # index to service queries against _type | ||||||
|  |         types_indexed = False | ||||||
|  |         def includes_types(fields): | ||||||
|  |             first_field = None | ||||||
|  |             if len(fields): | ||||||
|  |                 if isinstance(fields[0], basestring): | ||||||
|  |                     first_field = fields[0] | ||||||
|  |                 elif isinstance(fields[0], (list, tuple)) and len(fields[0]): | ||||||
|  |                     first_field = fields[0][0] | ||||||
|  |             return first_field == '_types' | ||||||
|  |  | ||||||
|  |         # Ensure indexes created by uniqueness constraints | ||||||
|  |         for index in self._document._meta['unique_indexes']: | ||||||
|  |             types_indexed = types_indexed or includes_types(index) | ||||||
|  |             self._collection.ensure_index(index, unique=True, | ||||||
|  |                 background=background, drop_dups=drop_dups, **index_opts) | ||||||
|  |  | ||||||
|  |         # Ensure document-defined indexes are created | ||||||
|  |         if self._document._meta['indexes']: | ||||||
|  |             for spec in self._document._meta['indexes']: | ||||||
|  |                 types_indexed = types_indexed or includes_types(spec['fields']) | ||||||
|  |                 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, | ||||||
|  |         # only if another index doesn't begin with _types | ||||||
|  |         if index_types and '_types' in self._query and not types_indexed: | ||||||
|  |             self._collection.ensure_index('_types', | ||||||
|  |                 background=background, **index_opts) | ||||||
|  |  | ||||||
|  |         # Add geo indicies | ||||||
|  |         for field in self._document._geo_indices(): | ||||||
|  |             index_spec = [(field.db_field, pymongo.GEO2D)] | ||||||
|  |             self._collection.ensure_index(index_spec, | ||||||
|  |                 background=background, **index_opts) | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def _collection(self): |     def _collection(self): | ||||||
|         """Property that returns the collection object. This allows us to |         """Property that returns the collection object. This allows us to | ||||||
|         perform operations only if the collection is accessed. |         perform operations only if the collection is accessed. | ||||||
|         """ |         """ | ||||||
|         if self._document not in QuerySet.__already_indexed: |         if self._document not in QuerySet.__already_indexed: | ||||||
|  |  | ||||||
|             # Ensure collection exists |             # Ensure collection exists | ||||||
|             db = self._document._get_db() |             db = self._document._get_db() | ||||||
|             if self._collection_obj.name not in db.collection_names(): |             if self._collection_obj.name not in db.collection_names(): | ||||||
| @@ -496,52 +543,8 @@ class QuerySet(object): | |||||||
|  |  | ||||||
|             QuerySet.__already_indexed.add(self._document) |             QuerySet.__already_indexed.add(self._document) | ||||||
|  |  | ||||||
|             background = self._document._meta.get('index_background', False) |             if self._document._meta.get('index_allow_creation', True): | ||||||
|             drop_dups = self._document._meta.get('index_drop_dups', False) |                 self._ensure_indexes_exist() | ||||||
|             index_opts = self._document._meta.get('index_options', {}) |  | ||||||
|             index_types = self._document._meta.get('index_types', True) |  | ||||||
|  |  | ||||||
|             # determine if an index which we are creating includes |  | ||||||
|             # _type as its first field; if so, we can avoid creating |  | ||||||
|             # an extra index on _type, as mongodb will use the existing |  | ||||||
|             # index to service queries against _type |  | ||||||
|             types_indexed = False |  | ||||||
|             def includes_types(fields): |  | ||||||
|                 first_field = None |  | ||||||
|                 if len(fields): |  | ||||||
|                     if isinstance(fields[0], basestring): |  | ||||||
|                         first_field = fields[0] |  | ||||||
|                     elif isinstance(fields[0], (list, tuple)) and len(fields[0]): |  | ||||||
|                         first_field = fields[0][0] |  | ||||||
|                 return first_field == '_types' |  | ||||||
|  |  | ||||||
|             # Ensure indexes created by uniqueness constraints |  | ||||||
|             for index in self._document._meta['unique_indexes']: |  | ||||||
|                 types_indexed = types_indexed or includes_types(index) |  | ||||||
|                 self._collection.ensure_index(index, unique=True, |  | ||||||
|                     background=background, drop_dups=drop_dups, **index_opts) |  | ||||||
|  |  | ||||||
|             # Ensure document-defined indexes are created |  | ||||||
|             if self._document._meta['indexes']: |  | ||||||
|                 for spec in self._document._meta['indexes']: |  | ||||||
|                     types_indexed = types_indexed or includes_types(spec['fields']) |  | ||||||
|                     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, |  | ||||||
|             # only if another index doesn't begin with _types |  | ||||||
|             if index_types and '_types' in self._query and not types_indexed: |  | ||||||
|                 self._collection.ensure_index('_types', |  | ||||||
|                     background=background, **index_opts) |  | ||||||
|  |  | ||||||
|             # Add geo indicies |  | ||||||
|             for field in self._document._geo_indices(): |  | ||||||
|                 index_spec = [(field.db_field, pymongo.GEO2D)] |  | ||||||
|                 self._collection.ensure_index(index_spec, |  | ||||||
|                     background=background, **index_opts) |  | ||||||
|  |  | ||||||
|         return self._collection_obj |         return self._collection_obj | ||||||
|  |  | ||||||
|   | |||||||
| @@ -740,6 +740,28 @@ class DocumentTest(unittest.TestCase): | |||||||
|         self.assertEqual(info.keys(), ['_types_1_user_guid_1', '_id_', '_types_1_name_1']) |         self.assertEqual(info.keys(), ['_types_1_user_guid_1', '_id_', '_types_1_name_1']) | ||||||
|         Person.drop_collection() |         Person.drop_collection() | ||||||
|  |  | ||||||
|  |     def test_disable_index_creation(self): | ||||||
|  |         """Tests setting allow_index_creation to False on the connection will | ||||||
|  |         disable any index generation. | ||||||
|  |         """ | ||||||
|  |         class User(Document): | ||||||
|  |             meta = { | ||||||
|  |                 'indexes': ['user_guid'], | ||||||
|  |                 'index_allow_creation': False | ||||||
|  |             } | ||||||
|  |             user_guid = StringField(required=True) | ||||||
|  |  | ||||||
|  |  | ||||||
|  |         User.drop_collection() | ||||||
|  |  | ||||||
|  |         u = User(user_guid='123') | ||||||
|  |         u.save() | ||||||
|  |  | ||||||
|  |         self.assertEquals(1, User.objects.count()) | ||||||
|  |         info = User.objects._collection.index_information() | ||||||
|  |         self.assertEqual(info.keys(), ['_id_']) | ||||||
|  |         User.drop_collection() | ||||||
|  |  | ||||||
|     def test_embedded_document_index(self): |     def test_embedded_document_index(self): | ||||||
|         """Tests settings an index on an embedded document |         """Tests settings an index on an embedded document | ||||||
|         """ |         """ | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user