33
44from django .db import NotSupportedError
55from django .db .models import (
6- BooleanField ,
7- CharField ,
8- DateField ,
9- DateTimeField ,
106 DecimalField ,
117 FloatField ,
128 Index ,
13- IntegerField ,
14- TextField ,
15- UUIDField ,
169)
1710from django .db .models .lookups import BuiltinLookup
1811from django .db .models .sql .query import Query
1912from django .db .models .sql .where import AND , XOR , WhereNode
2013from pymongo import ASCENDING , DESCENDING
2114from pymongo .operations import IndexModel , SearchIndexModel
2215
23- from django_mongodb_backend .fields import ArrayField , ObjectIdAutoField , ObjectIdField
16+ from django_mongodb_backend .fields import ArrayField
2417
2518from .query_utils import process_rhs
2619
@@ -76,7 +69,7 @@ def where_node_idx(self, compiler, connection):
7669 return mql
7770
7871
79- def create_mongodb_index (
72+ def get_pymongo_index_model (
8073 self ,
8174 model ,
8275 schema_editor ,
@@ -124,57 +117,41 @@ def create_mongodb_index(
124117
125118class SearchIndex (Index ):
126119 suffix = "search"
127- # Maps Django internal type to atlas search index type.
128- search_index_data_types = {
129- "AutoField" : "number" ,
130- "BigAutoField" : "number" ,
131- "BinaryField" : "string" ,
132- "BooleanField" : "boolean" ,
133- "CharField" : "string" ,
134- "DateField" : "date" ,
135- "DateTimeField" : "date" ,
136- "DecimalField" : "number" ,
137- "DurationField" : "number" ,
138- "FileField" : "string" ,
139- "FilePathField" : "string" ,
140- "FloatField" : "double" ,
141- "IntegerField" : "number" ,
142- "BigIntegerField" : "number" ,
143- "GenericIPAddressField" : "string" ,
144- "JSONField" : "document" ,
145- "OneToOneField" : "number" ,
146- "PositiveBigIntegerField" : "number" ,
147- "PositiveIntegerField" : "number" ,
148- "PositiveSmallIntegerField" : "number" ,
149- "SlugField" : "string" ,
150- "SmallAutoField" : "number" ,
151- "SmallIntegerField" : "number" ,
152- "TextField" : "string" ,
153- "TimeField" : "date" ,
154- "UUIDField" : "uuid" ,
155- "ObjectIdAutoField" : "objectId" ,
156- "ObjectIdField" : "objectId" ,
157- "EmbeddedModelField" : "embeddedDocuments" ,
158- }
159-
160- def __init__ (self , * expressions , ** kwargs ):
161- super ().__init__ (* expressions , ** kwargs )
162120
163- def create_mongodb_index (
121+ # Maps Django internal type to atlas search index type.
122+ # Reference: https://www.mongodb.com/docs/atlas/atlas-search/define-field-mappings/#data-types
123+ def search_index_data_types (self , field , db_type ):
124+ if field .get_internal_type () == "UUIDField" :
125+ return "uuid"
126+ if field .get_internal_type () in ("ObjectIdAutoField" , "ObjectIdField" ):
127+ return "ObjectId"
128+ if field .get_internal_type () == "EmbeddedModelField" :
129+ return "embeddedDocuments"
130+ if db_type in ("int" , "long" ):
131+ return "number"
132+ if db_type == "binData" :
133+ return "string"
134+ if db_type == "bool" :
135+ return "boolean"
136+ if db_type == "object" :
137+ return "document"
138+ return db_type
139+
140+ def get_pymongo_index_model (
164141 self , model , schema_editor , field = None , unique = False , column_prefix = ""
165142 ):
166143 fields = {}
167144 for field_name , _ in self .fields_orders :
168145 field_ = model ._meta .get_field (field_name )
169- type_ = self .search_index_data_types [ field_ . get_internal_type ()]
146+ type_ = self .search_index_data_types ( field_ , field_ . db_type ( schema_editor . connection ))
170147 field_path = column_prefix + model ._meta .get_field (field_name ).column
171148 fields [field_path ] = {"type" : type_ }
172149 return SearchIndexModel (
173150 definition = {"mappings" : {"dynamic" : False , "fields" : fields }}, name = self .name
174151 )
175152
176153
177- class VectorSearchIndex (Index ):
154+ class VectorSearchIndex (SearchIndex ):
178155 suffix = "vector_search"
179156 ALLOWED_SIMILARITY_FUNCTIONS = frozenset (("euclidean" , "cosine" , "dotProduct" ))
180157
@@ -195,7 +172,7 @@ def _check_similarity_functions(self, similarities):
195172 f"'are { ',' .join (self .ALLOWED_SIMILARITY_FUNCTIONS )} "
196173 )
197174
198- def create_mongodb_index (
175+ def get_pymongo_index_model (
199176 self , model , schema_editor , field = None , unique = False , column_prefix = ""
200177 ):
201178 similarities = (
@@ -222,28 +199,23 @@ def create_mongodb_index(
222199 "similarity" : next (similarities ),
223200 }
224201 )
225- elif isinstance (
226- field_ ,
227- BooleanField
228- | IntegerField
229- | DateField
230- | DateTimeField
231- | CharField
232- | TextField
233- | UUIDField
234- | ObjectIdField
235- | ObjectIdAutoField ,
236- ):
237- mappings ["type" ] = "filter"
238202 else :
239- field_type = field_ .get_internal_type ()
240- raise ValueError (f"Unsupported filter of type { field_type } ." )
203+ field_type = field_ .db_type (schema_editor .connection )
204+ search_type = self .search_index_data_types (field_ , field_type )
205+ # filter - for fields that contain boolean, date, objectId, numeric,
206+ # string, or UUID values. Reference:
207+ # https://www.mongodb.com/docs/atlas/atlas-vector-search/vector-search-type/#atlas-vector-search-index-fields
208+ if search_type in ("number" , "string" , "boolean" , "objectId" , "uuid" , "date" ):
209+ mappings ["type" ] = "filter"
210+ else :
211+ field_type = field_ .get_internal_type ()
212+ raise ValueError (f"Unsupported filter of type { field_type } ." )
241213 fields .append (mappings )
242214 return SearchIndexModel (definition = {"fields" : fields }, name = self .name , type = "vectorSearch" )
243215
244216
245217def register_indexes ():
246218 BuiltinLookup .as_mql_idx = builtin_lookup_idx
247219 Index ._get_condition_mql = _get_condition_mql
248- Index .create_mongodb_index = create_mongodb_index
220+ Index .get_pymongo_index_model = get_pymongo_index_model
249221 WhereNode .as_mql_idx = where_node_idx
0 commit comments