Skip to content

Commit daae732

Browse files
Jibolatimgraham
authored andcommitted
INTPYTHON-729 Allow creating search indexes with field mappings
1 parent 2787e0d commit daae732

File tree

1 file changed

+35
-6
lines changed

1 file changed

+35
-6
lines changed

django_mongodb_backend/indexes.py

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
164193
class 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

Comments
 (0)