@@ -109,9 +109,22 @@ class SearchIndex(Index):
109109 suffix = "six"
110110 _error_id_prefix = "django_mongodb_backend.indexes.SearchIndex"
111111
112- def __init__ (self , * , fields = (), name = None ):
112+ def __init__ (self , * , fields = (), name = None , field_mappings = None ):
113+ if field_mappings and not isinstance (field_mappings , dict ):
114+ raise ValueError (
115+ "field_mappings must be a dictionary mapping field names to their "
116+ "Atlas Search field mappings."
117+ )
118+ self .field_mappings = field_mappings or {}
119+
120+ fields = list ({* fields , * self .field_mappings .keys ()})
113121 super ().__init__ (fields = fields , name = name )
114122
123+ def deconstruct (self ):
124+ path , args , kwargs = super ().deconstruct ()
125+ kwargs ["field_mappings" ] = self .field_mappings
126+ return path , args , kwargs
127+
115128 def check (self , model , connection ):
116129 errors = []
117130 if not connection .features .supports_atlas_search :
@@ -152,23 +165,39 @@ def get_pymongo_index_model(
152165 return None
153166 fields = {}
154167 for field_name , _ in self .fields_orders :
155- field = model ._meta .get_field (field_name )
156- type_ = self .search_index_data_types (field .db_type (schema_editor .connection ))
157168 field_path = column_prefix + model ._meta .get_field (field_name ).column
158- fields [field_path ] = {"type" : type_ }
169+ if field_name in self .field_mappings :
170+ fields [field_path ] = self .field_mappings [field_name ].copy ()
171+ else :
172+ # If no field mapping is provided, use the default search index data type.
173+ field = model ._meta .get_field (field_name )
174+ type_ = self .search_index_data_types (field .db_type (schema_editor .connection ))
175+ fields [field_path ] = {"type" : type_ }
159176 return SearchIndexModel (
160177 definition = {"mappings" : {"dynamic" : False , "fields" : fields }}, name = self .name
161178 )
162179
163180
181+ class DynamicSearchIndex (SearchIndex ):
182+ suffix = "dsix"
183+ _error_id_prefix = "django_mongodb_backend.indexes.DynamicSearchIndex"
184+
185+ def get_pymongo_index_model (
186+ self , model , schema_editor , field = None , unique = False , column_prefix = ""
187+ ):
188+ if not schema_editor .connection .features .supports_atlas_search :
189+ return None
190+ return SearchIndexModel (definition = {"mappings" : {"dynamic" : True }}, name = self .name )
191+
192+
164193class VectorSearchIndex (SearchIndex ):
165194 suffix = "vsi"
166195 _error_id_prefix = "django_mongodb_backend.indexes.VectorSearchIndex"
167196 VALID_FIELD_TYPES = frozenset (("boolean" , "date" , "number" , "objectId" , "string" , "uuid" ))
168197 VALID_SIMILARITIES = frozenset (("cosine" , "dotProduct" , "euclidean" ))
169198
170- def __init__ (self , * , fields = (), name = None , similarities ):
171- super ().__init__ (fields = fields , name = name )
199+ def __init__ (self , * , fields = (), name = None , similarities = (), fields_mappings = None ):
200+ super ().__init__ (fields = fields , name = name , field_mappings = fields_mappings )
172201 self .similarities = similarities
173202 self ._multiple_similarities = isinstance (similarities , tuple | list )
174203 for func in similarities if self ._multiple_similarities else (similarities ,):
0 commit comments