Skip to content

Commit 6d4c987

Browse files
committed
Docstring and search type mapping
1 parent 49ae8e9 commit 6d4c987

File tree

1 file changed

+36
-64
lines changed

1 file changed

+36
-64
lines changed

django_mongodb_backend/indexes.py

Lines changed: 36 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,17 @@
33

44
from django.db import NotSupportedError
55
from 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
)
1710
from django.db.models.lookups import BuiltinLookup
1811
from django.db.models.sql.query import Query
1912
from django.db.models.sql.where import AND, XOR, WhereNode
2013
from pymongo import ASCENDING, DESCENDING
2114
from 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

2518
from .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

125118
class 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

245217
def 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

Comments
 (0)