@@ -109,9 +109,22 @@ class SearchIndex(Index):
109
109
suffix = "six"
110
110
_error_id_prefix = "django_mongodb_backend.indexes.SearchIndex"
111
111
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 ()})
113
121
super ().__init__ (fields = fields , name = name )
114
122
123
+ def deconstruct (self ):
124
+ path , args , kwargs = super ().deconstruct ()
125
+ kwargs ["field_mappings" ] = self .field_mappings
126
+ return path , args , kwargs
127
+
115
128
def check (self , model , connection ):
116
129
errors = []
117
130
if not connection .features .supports_atlas_search :
@@ -152,23 +165,39 @@ def get_pymongo_index_model(
152
165
return None
153
166
fields = {}
154
167
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 ))
157
168
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_ }
159
176
return SearchIndexModel (
160
177
definition = {"mappings" : {"dynamic" : False , "fields" : fields }}, name = self .name
161
178
)
162
179
163
180
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
+
164
193
class VectorSearchIndex (SearchIndex ):
165
194
suffix = "vsi"
166
195
_error_id_prefix = "django_mongodb_backend.indexes.VectorSearchIndex"
167
196
VALID_FIELD_TYPES = frozenset (("boolean" , "date" , "number" , "objectId" , "string" , "uuid" ))
168
197
VALID_SIMILARITIES = frozenset (("cosine" , "dotProduct" , "euclidean" ))
169
198
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 )
172
201
self .similarities = similarities
173
202
self ._multiple_similarities = isinstance (similarities , tuple | list )
174
203
for func in similarities if self ._multiple_similarities else (similarities ,):
0 commit comments