55from pymongo import ASCENDING , DESCENDING
66from pymongo .operations import IndexModel
77
8+ from .fields import EmbeddedModelField
89from .query import wrap_database_errors
910from .utils import OperationCollector
1011
@@ -29,25 +30,40 @@ def create_model(self, model):
2930 if field .remote_field .through ._meta .auto_created :
3031 self .create_model (field .remote_field .through )
3132
32- def _create_model_indexes (self , model ):
33+ def _create_model_indexes (self , model , column_prefix = "" , parent_model = None ):
3334 """
3435 Create all indexes (field indexes & uniques, Meta.index_together,
3536 Meta.unique_together, Meta.constraints, Meta.indexes) for the model.
37+
38+ If this is a recursive call to due to an embedded model, `column_prefix`
39+ tracks the path that must be prepended to the index's column, and
40+ `parent_model` tracks the collection to add the index/constraint to.
3641 """
3742 if not model ._meta .managed or model ._meta .proxy or model ._meta .swapped :
3843 return
3944 # Field indexes and uniques
4045 for field in model ._meta .local_fields :
46+ if isinstance (field , EmbeddedModelField ):
47+ new_path = f"{ column_prefix } { field .column } ."
48+ self ._create_model_indexes (
49+ field .embedded_model , parent_model = parent_model or model , column_prefix = new_path
50+ )
4151 if self ._field_should_be_indexed (model , field ):
42- self ._add_field_index (model , field )
52+ self ._add_field_index (parent_model or model , field , column_prefix = column_prefix )
4353 elif self ._field_should_have_unique (field ):
44- self ._add_field_unique (model , field )
54+ self ._add_field_unique (parent_model or model , field , column_prefix = column_prefix )
4555 # Meta.index_together (RemovedInDjango51Warning)
4656 for field_names in model ._meta .index_together :
4757 self ._add_composed_index (model , field_names )
4858 # Meta.unique_together
4959 if model ._meta .unique_together :
50- self .alter_unique_together (model , [], model ._meta .unique_together )
60+ self .alter_unique_together (
61+ model ,
62+ [],
63+ model ._meta .unique_together ,
64+ column_prefix = column_prefix ,
65+ parent_model = parent_model ,
66+ )
5167 # Meta.constraints
5268 for constraint in model ._meta .constraints :
5369 self .add_constraint (model , constraint )
@@ -147,7 +163,9 @@ def alter_index_together(self, model, old_index_together, new_index_together):
147163 for field_names in news .difference (olds ):
148164 self ._add_composed_index (model , field_names )
149165
150- def alter_unique_together (self , model , old_unique_together , new_unique_together ):
166+ def alter_unique_together (
167+ self , model , old_unique_together , new_unique_together , column_prefix = "" , parent_model = None
168+ ):
151169 olds = {tuple (fields ) for fields in old_unique_together }
152170 news = {tuple (fields ) for fields in new_unique_together }
153171 # Deleted uniques
@@ -160,11 +178,19 @@ def alter_unique_together(self, model, old_unique_together, new_unique_together)
160178 # Created uniques
161179 for field_names in news .difference (olds ):
162180 columns = [model ._meta .get_field (field ).column for field in field_names ]
163- name = str (self ._unique_constraint_name (model ._meta .db_table , columns ))
181+ name = str (
182+ self ._unique_constraint_name (
183+ model ._meta .db_table , [column_prefix + col for col in columns ]
184+ )
185+ )
164186 constraint = UniqueConstraint (fields = field_names , name = name )
165- self .add_constraint (model , constraint )
187+ self .add_constraint (
188+ model , constraint , parent_model = parent_model , column_prefix = column_prefix
189+ )
166190
167- def add_index (self , model , index , field = None , unique = False ):
191+ def add_index (
192+ self , model , index , * , field = None , unique = False , column_prefix = "" , parent_model = None
193+ ):
168194 if index .contains_expressions :
169195 return
170196 kwargs = {}
@@ -176,7 +202,8 @@ def add_index(self, model, index, field=None, unique=False):
176202 # Indexing on $type matches the value of most SQL databases by
177203 # allowing multiple null values for the unique constraint.
178204 if field :
179- filter_expression [field .column ].update ({"$type" : field .db_type (self .connection )})
205+ column = column_prefix + field .column
206+ filter_expression [column ].update ({"$type" : field .db_type (self .connection )})
180207 else :
181208 for field_name , _ in index .fields_orders :
182209 field_ = model ._meta .get_field (field_name )
@@ -186,16 +213,20 @@ def add_index(self, model, index, field=None, unique=False):
186213 if filter_expression :
187214 kwargs ["partialFilterExpression" ] = filter_expression
188215 index_orders = (
189- [(field .column , ASCENDING )]
216+ [(column_prefix + field .column , ASCENDING )]
190217 if field
191218 else [
192219 # order is "" if ASCENDING or "DESC" if DESCENDING (see
193220 # django.db.models.indexes.Index.fields_orders).
194- (model ._meta .get_field (field_name ).column , ASCENDING if order == "" else DESCENDING )
221+ (
222+ column_prefix + model ._meta .get_field (field_name ).column ,
223+ ASCENDING if order == "" else DESCENDING ,
224+ )
195225 for field_name , order in index .fields_orders
196226 ]
197227 )
198228 idx = IndexModel (index_orders , name = index .name , ** kwargs )
229+ model = parent_model or model
199230 self .get_collection (model ._meta .db_table ).create_indexes ([idx ])
200231
201232 def _add_composed_index (self , model , field_names ):
@@ -204,11 +235,11 @@ def _add_composed_index(self, model, field_names):
204235 idx .set_name_with_model (model )
205236 self .add_index (model , idx )
206237
207- def _add_field_index (self , model , field ):
238+ def _add_field_index (self , model , field , * , column_prefix = "" ):
208239 """Add an index on a field with db_index=True."""
209- index = Index (fields = [field .name ])
210- index .name = self ._create_index_name (model ._meta .db_table , [field .column ])
211- self .add_index (model , index , field = field )
240+ index = Index (fields = [column_prefix + field .name ])
241+ index .name = self ._create_index_name (model ._meta .db_table , [column_prefix + field .column ])
242+ self .add_index (model , index , field = field , column_prefix = column_prefix )
212243
213244 def remove_index (self , model , index ):
214245 if index .contains_expressions :
@@ -260,7 +291,7 @@ def _remove_field_index(self, model, field):
260291 )
261292 collection .drop_index (index_names [0 ])
262293
263- def add_constraint (self , model , constraint , field = None ):
294+ def add_constraint (self , model , constraint , field = None , column_prefix = "" , parent_model = None ):
264295 if isinstance (constraint , UniqueConstraint ) and self ._unique_supported (
265296 condition = constraint .condition ,
266297 deferrable = constraint .deferrable ,
@@ -273,12 +304,21 @@ def add_constraint(self, model, constraint, field=None):
273304 name = constraint .name ,
274305 condition = constraint .condition ,
275306 )
276- self .add_index (model , idx , field = field , unique = True )
307+ self .add_index (
308+ model ,
309+ idx ,
310+ field = field ,
311+ unique = True ,
312+ column_prefix = column_prefix ,
313+ parent_model = parent_model ,
314+ )
277315
278- def _add_field_unique (self , model , field ):
279- name = str (self ._unique_constraint_name (model ._meta .db_table , [field .column ]))
316+ def _add_field_unique (self , model , field , column_prefix = "" ):
317+ name = str (
318+ self ._unique_constraint_name (model ._meta .db_table , [column_prefix + field .column ])
319+ )
280320 constraint = UniqueConstraint (fields = [field .name ], name = name )
281- self .add_constraint (model , constraint , field = field )
321+ self .add_constraint (model , constraint , field = field , column_prefix = column_prefix )
282322
283323 def remove_constraint (self , model , constraint ):
284324 if isinstance (constraint , UniqueConstraint ) and self ._unique_supported (
0 commit comments