@@ -85,17 +85,19 @@ def test_multiple_fields(self):
8585 def test_field_not_exists (self ):
8686 index = AtlasSearchIndex (
8787 name = "recent_article_idx" ,
88- fields = ["headline" , "number1 " ],
88+ fields = ["headline" , "non_existing_name " ],
8989 )
9090 with connection .schema_editor () as editor :
91- msg = "Article has no field named 'number1 '"
91+ msg = "Article has no field named 'non_existing_name '"
9292 with self .assertRaisesMessage (
9393 FieldDoesNotExist , msg
9494 ), connection .schema_editor () as editor :
9595 editor .add_index (index = index , model = Article )
9696
9797
98- class AtlasIndexTestsWithData (AtlasIndexTests ):
98+ class AtlasIndexTestsWithData (TestCase ):
99+ available_apps = None
100+
99101 @classmethod
100102 def setUpTestData (cls ):
101103 articles = [
@@ -115,6 +117,74 @@ def setUpTestData(cls):
115117 ]
116118 cls .objs = Article .objects .bulk_create (articles )
117119
120+ def assertAddRemoveIndex (self , editor , model , index ):
121+ editor .add_index (index = index , model = model )
122+ self .assertIn (
123+ index .name ,
124+ connection .introspection .get_constraints (
125+ cursor = None ,
126+ table_name = model ._meta .db_table ,
127+ ),
128+ )
129+ editor .remove_index (index = index , model = model )
130+ self .assertNotIn (
131+ index .name ,
132+ connection .introspection .get_constraints (
133+ cursor = None ,
134+ table_name = model ._meta .db_table ,
135+ ),
136+ )
137+
138+ def test_simple (self ):
139+ with connection .schema_editor () as editor :
140+ index = AtlasSearchIndex (
141+ name = "recent_article_idx" ,
142+ fields = ["number" ],
143+ )
144+ editor .add_index (index = index , model = Article )
145+ self .assertAddRemoveIndex (editor , Article , index )
146+
147+ def test_multiple_fields (self ):
148+ with connection .schema_editor () as editor :
149+ index = AtlasSearchIndex (
150+ name = "recent_article_idx" ,
151+ fields = ["headline" , "number" , "body" , "data" , "embedded" , "auto_now" ],
152+ )
153+ editor .add_index (index = index , model = Article )
154+ index_info = connection .introspection .get_constraints (
155+ cursor = None ,
156+ table_name = Article ._meta .db_table ,
157+ )
158+ expected_options = {
159+ "dynamic" : False ,
160+ "fields" : {
161+ "auto_now" : {"type" : "date" },
162+ "body" : {
163+ "indexOptions" : "offsets" ,
164+ "norms" : "include" ,
165+ "store" : True ,
166+ "type" : "string" ,
167+ },
168+ "data" : {"dynamic" : False , "fields" : {}, "type" : "document" },
169+ "embedded" : {"dynamic" : False , "fields" : {}, "type" : "embeddedDocuments" },
170+ "headline" : {
171+ "indexOptions" : "offsets" ,
172+ "norms" : "include" ,
173+ "store" : True ,
174+ "type" : "string" ,
175+ },
176+ "number" : {
177+ "indexDoubles" : True ,
178+ "indexIntegers" : True ,
179+ "representation" : "double" ,
180+ "type" : "number" ,
181+ },
182+ },
183+ }
184+ self .assertCountEqual (index_info [index .name ]["columns" ], index .fields )
185+ self .assertEqual (index_info [index .name ]["options" ], expected_options )
186+ self .assertAddRemoveIndex (editor , Article , index )
187+
118188
119189class AtlasSearchIndexTests (TestCase ):
120190 # Schema editor is used to create the index to test that it works.
@@ -187,17 +257,19 @@ def test_multiple_fields(self):
187257 def test_field_not_exists (self ):
188258 index = AtlasVectorSearchIndex (
189259 name = "recent_article_idx" ,
190- fields = ["headline" , "number1 " , "title_embedded" ],
260+ fields = ["headline" , "non_existing_name " , "title_embedded" ],
191261 )
192262 with connection .schema_editor () as editor :
193- msg = "Article has no field named 'number1 '"
263+ msg = "Article has no field named 'non_existing_name '"
194264 with self .assertRaisesMessage (
195265 FieldDoesNotExist , msg
196266 ), connection .schema_editor () as editor :
197267 editor .add_index (index = index , model = Article )
198268
199269
200- class AtlasSearchIndexTestsWithData (AtlasSearchIndexTests ):
270+ class AtlasSearchIndexTestsWithData (TestCase ):
271+ available_apps = None # could be removed?
272+
201273 @classmethod
202274 def setUpTestData (cls ):
203275 articles = [
@@ -216,3 +288,88 @@ def setUpTestData(cls):
216288 for i in range (5 )
217289 ]
218290 cls .objs = Article .objects .bulk_create (articles )
291+
292+ def assertAddRemoveIndex (self , editor , model , index ):
293+ editor .add_index (index = index , model = model )
294+ self .assertIn (
295+ index .name ,
296+ connection .introspection .get_constraints (
297+ cursor = None ,
298+ table_name = model ._meta .db_table ,
299+ ),
300+ )
301+ editor .remove_index (index = index , model = model )
302+ self .assertNotIn (
303+ index .name ,
304+ connection .introspection .get_constraints (
305+ cursor = None ,
306+ table_name = model ._meta .db_table ,
307+ ),
308+ )
309+
310+ def test_simple_atlas_vector_search (self ):
311+ with connection .schema_editor () as editor :
312+ index = AtlasVectorSearchIndex (
313+ name = "recent_article_idx" ,
314+ fields = ["number" ],
315+ )
316+ editor .add_index (index = index , model = Article )
317+ self .assertAddRemoveIndex (editor , Article , index )
318+
319+ def test_multiple_fields (self ):
320+ with connection .schema_editor () as editor :
321+ index = AtlasVectorSearchIndex (
322+ name = "recent_article_idx" ,
323+ fields = ["headline" , "number" , "body" , "description_embedded" ],
324+ )
325+ editor .add_index (index = index , model = Article )
326+ index_info = connection .introspection .get_constraints (
327+ cursor = None ,
328+ table_name = Article ._meta .db_table ,
329+ )
330+ expected_options = {
331+ "latestDefinition" : {
332+ "fields" : [
333+ {"path" : "headline" , "type" : "filter" },
334+ {"path" : "number" , "type" : "filter" },
335+ {"path" : "body" , "type" : "filter" },
336+ {
337+ "numDimensions" : 10 ,
338+ "path" : "description_embedded" ,
339+ "similarity" : "cosine" ,
340+ "type" : "vector" ,
341+ },
342+ ]
343+ },
344+ "latestVersion" : 0 ,
345+ "name" : "recent_article_idx" ,
346+ "queryable" : False ,
347+ "type" : "vectorSearch" ,
348+ }
349+ self .assertCountEqual (index_info [index .name ]["columns" ], index .fields )
350+ index_info [index .name ]["options" ].pop ("id" )
351+ index_info [index .name ]["options" ].pop ("status" )
352+ self .assertEqual (index_info [index .name ]["options" ], expected_options )
353+ self .assertAddRemoveIndex (editor , Article , index )
354+
355+ def test_corrupted_data (self ):
356+ # Mongodb does not raises anything when some vector does not fulfill the required size
357+ with connection .schema_editor () as editor :
358+ Article .objects .create (
359+ headline = "Title" ,
360+ number = 10 ,
361+ body = f"body { 10 } " ,
362+ data = "{json: 3}" ,
363+ embedded = Data (integer = 3 ),
364+ auto_now = datetime .datetime .now (),
365+ title_embedded = [0.1 ] * 15 ,
366+ description_embedded = [2.5 ] * 16 , # it does not have the required size of ten.
367+ number_list = [2 ] * 22 ,
368+ name_list = [f"name_{ 2 } " ] * 7 ,
369+ )
370+ index = AtlasVectorSearchIndex (
371+ name = "recent_article_idx" ,
372+ fields = ["headline" , "number" , "body" , "description_embedded" ],
373+ )
374+ editor .add_index (index = index , model = Article )
375+ self .assertAddRemoveIndex (editor , Article , index )
0 commit comments