4
4
5
5
from django .db import NotSupportedError
6
6
from django .db .models import (
7
- BooleanField ,
8
- CharField ,
9
- DateField ,
10
- DateTimeField ,
11
7
DecimalField ,
12
8
FloatField ,
13
9
Index ,
14
- IntegerField ,
15
- TextField ,
16
- UUIDField ,
17
10
)
18
11
from django .db .models .lookups import BuiltinLookup
19
12
from django .db .models .sql .query import Query
20
13
from django .db .models .sql .where import AND , XOR , WhereNode
21
14
from pymongo import ASCENDING , DESCENDING
22
15
from pymongo .operations import IndexModel , SearchIndexModel
23
16
24
- from django_mongodb_backend .fields import ArrayField , ObjectIdAutoField , ObjectIdField
17
+ from django_mongodb_backend .fields import ArrayField
25
18
26
19
from .query_utils import process_rhs
27
20
@@ -116,7 +109,7 @@ def where_node_idx(self, compiler, connection):
116
109
return mql
117
110
118
111
119
- def create_mongodb_index (
112
+ def get_pymongo_index_model (
120
113
self ,
121
114
model ,
122
115
schema_editor ,
@@ -164,57 +157,41 @@ def create_mongodb_index(
164
157
165
158
class SearchIndex (Index ):
166
159
suffix = "search"
167
- # Maps Django internal type to atlas search index type.
168
- search_index_data_types = {
169
- "AutoField" : "number" ,
170
- "BigAutoField" : "number" ,
171
- "BinaryField" : "string" ,
172
- "BooleanField" : "boolean" ,
173
- "CharField" : "string" ,
174
- "DateField" : "date" ,
175
- "DateTimeField" : "date" ,
176
- "DecimalField" : "number" ,
177
- "DurationField" : "number" ,
178
- "FileField" : "string" ,
179
- "FilePathField" : "string" ,
180
- "FloatField" : "double" ,
181
- "IntegerField" : "number" ,
182
- "BigIntegerField" : "number" ,
183
- "GenericIPAddressField" : "string" ,
184
- "JSONField" : "document" ,
185
- "OneToOneField" : "number" ,
186
- "PositiveBigIntegerField" : "number" ,
187
- "PositiveIntegerField" : "number" ,
188
- "PositiveSmallIntegerField" : "number" ,
189
- "SlugField" : "string" ,
190
- "SmallAutoField" : "number" ,
191
- "SmallIntegerField" : "number" ,
192
- "TextField" : "string" ,
193
- "TimeField" : "date" ,
194
- "UUIDField" : "uuid" ,
195
- "ObjectIdAutoField" : "objectId" ,
196
- "ObjectIdField" : "objectId" ,
197
- "EmbeddedModelField" : "embeddedDocuments" ,
198
- }
199
160
200
- def __init__ (self , * expressions , ** kwargs ):
201
- super ().__init__ (* expressions , ** kwargs )
161
+ # Maps Django internal type to atlas search index type.
162
+ # Reference: https://www.mongodb.com/docs/atlas/atlas-search/define-field-mappings/#data-types
163
+ def search_index_data_types (self , field , db_type ):
164
+ if field .get_internal_type () == "UUIDField" :
165
+ return "uuid"
166
+ if field .get_internal_type () in ("ObjectIdAutoField" , "ObjectIdField" ):
167
+ return "ObjectId"
168
+ if field .get_internal_type () == "EmbeddedModelField" :
169
+ return "embeddedDocuments"
170
+ if db_type in ("int" , "long" ):
171
+ return "number"
172
+ if db_type == "binData" :
173
+ return "string"
174
+ if db_type == "bool" :
175
+ return "boolean"
176
+ if db_type == "object" :
177
+ return "document"
178
+ return db_type
202
179
203
- def create_mongodb_index (
180
+ def get_pymongo_index_model (
204
181
self , model , schema_editor , field = None , unique = False , column_prefix = ""
205
182
):
206
183
fields = {}
207
184
for field_name , _ in self .fields_orders :
208
185
field_ = model ._meta .get_field (field_name )
209
- type_ = self .search_index_data_types [ field_ . get_internal_type ()]
186
+ type_ = self .search_index_data_types ( field_ , field_ . db_type ( schema_editor . connection ))
210
187
field_path = column_prefix + model ._meta .get_field (field_name ).column
211
188
fields [field_path ] = {"type" : type_ }
212
189
return SearchIndexModel (
213
190
definition = {"mappings" : {"dynamic" : False , "fields" : fields }}, name = self .name
214
191
)
215
192
216
193
217
- class VectorSearchIndex (Index ):
194
+ class VectorSearchIndex (SearchIndex ):
218
195
suffix = "vector_search"
219
196
ALLOWED_SIMILARITY_FUNCTIONS = frozenset (("euclidean" , "cosine" , "dotProduct" ))
220
197
@@ -235,7 +212,7 @@ def _check_similarity_functions(self, similarities):
235
212
f"'are { ',' .join (self .ALLOWED_SIMILARITY_FUNCTIONS )} "
236
213
)
237
214
238
- def create_mongodb_index (
215
+ def get_pymongo_index_model (
239
216
self , model , schema_editor , field = None , unique = False , column_prefix = ""
240
217
):
241
218
similarities = (
@@ -262,22 +239,17 @@ def create_mongodb_index(
262
239
"similarity" : next (similarities ),
263
240
}
264
241
)
265
- elif isinstance (
266
- field_ ,
267
- BooleanField
268
- | IntegerField
269
- | DateField
270
- | DateTimeField
271
- | CharField
272
- | TextField
273
- | UUIDField
274
- | ObjectIdField
275
- | ObjectIdAutoField ,
276
- ):
277
- mappings ["type" ] = "filter"
278
242
else :
279
- field_type = field_ .get_internal_type ()
280
- raise ValueError (f"Unsupported filter of type { field_type } ." )
243
+ field_type = field_ .db_type (schema_editor .connection )
244
+ search_type = self .search_index_data_types (field_ , field_type )
245
+ # filter - for fields that contain boolean, date, objectId, numeric,
246
+ # string, or UUID values. Reference:
247
+ # https://www.mongodb.com/docs/atlas/atlas-vector-search/vector-search-type/#atlas-vector-search-index-fields
248
+ if search_type in ("number" , "string" , "boolean" , "objectId" , "uuid" , "date" ):
249
+ mappings ["type" ] = "filter"
250
+ else :
251
+ field_type = field_ .get_internal_type ()
252
+ raise ValueError (f"Unsupported filter of type { field_type } ." )
281
253
fields .append (mappings )
282
254
return SearchIndexModel (definition = {"fields" : fields }, name = self .name , type = "vectorSearch" )
283
255
0 commit comments