8
8
from django .db .models .query import QuerySet
9
9
from django .db .utils import DatabaseError
10
10
from django .test import TransactionTestCase , skipUnlessDBFeature
11
- from pymongo .operations import SearchIndexModel
12
11
13
12
from django_mongodb_backend .expressions import (
14
13
CompoundExpression ,
28
27
SearchVector ,
29
28
SearchWildcard ,
30
29
)
31
- from django_mongodb_backend .schema import DatabaseSchemaEditor
30
+ from django_mongodb_backend .indexes import SearchIndex , VectorSearchIndex
32
31
33
32
from .models import Article , Location , Writer
34
33
@@ -75,22 +74,15 @@ class SearchUtilsMixin(TransactionTestCase):
75
74
assertListEqual = _delayed_assertion (timeout = 2 )(TransactionTestCase .assertListEqual )
76
75
assertQuerySetEqual = _delayed_assertion (timeout = 2 )(TransactionTestCase .assertQuerySetEqual )
77
76
78
- @staticmethod
79
- def _get_collection (model ):
80
- return connection .database .get_collection (model ._meta .db_table )
81
-
82
77
@classmethod
83
- def create_search_index (cls , model , index_name , definition , type = "search" ):
84
- # TODO: create/delete indexes using DatabaseSchemaEditor when
85
- # SearchIndexes support mappings (INTPYTHON-729).
86
- collection = cls ._get_collection (model )
87
- idx = SearchIndexModel (definition = definition , name = index_name , type = type )
88
- collection .create_search_index (idx )
89
- DatabaseSchemaEditor .wait_until_index_created (collection , index_name )
78
+ def create_search_index (cls , model , index_name , definition , index_cls = SearchIndex ):
79
+ idx = index_cls (field_mappings = definition , name = index_name )
80
+ with connection .schema_editor () as editor :
81
+ editor .add_index (model , idx )
90
82
91
83
def drop_index ():
92
- collection . drop_search_index ( index_name )
93
- DatabaseSchemaEditor . wait_until_index_dropped ( collection , index_name )
84
+ with connection . schema_editor () as editor :
85
+ editor . remove_index ( model , idx )
94
86
95
87
cls .addClassCleanup (drop_index )
96
88
@@ -101,12 +93,7 @@ def setUpClass(cls):
101
93
cls .create_search_index (
102
94
Article ,
103
95
"equals_headline_index" ,
104
- {
105
- "mappings" : {
106
- "dynamic" : False ,
107
- "fields" : {"headline" : {"type" : "token" }, "number" : {"type" : "number" }},
108
- }
109
- },
96
+ {"headline" : {"type" : "token" }, "number" : {"type" : "number" }},
110
97
)
111
98
112
99
def setUp (self ):
@@ -167,32 +154,27 @@ def setUpClass(cls):
167
154
Article ,
168
155
"autocomplete_headline_index" ,
169
156
{
170
- "mappings" : {
171
- "dynamic" : False ,
157
+ "headline" : {
158
+ "type" : "autocomplete" ,
159
+ "analyzer" : "lucene.standard" ,
160
+ "tokenization" : "edgeGram" ,
161
+ "minGrams" : 3 ,
162
+ "maxGrams" : 5 ,
163
+ "foldDiacritics" : False ,
164
+ },
165
+ "writer" : {
166
+ "type" : "document" ,
172
167
"fields" : {
173
- "headline " : {
168
+ "name " : {
174
169
"type" : "autocomplete" ,
175
170
"analyzer" : "lucene.standard" ,
176
171
"tokenization" : "edgeGram" ,
177
172
"minGrams" : 3 ,
178
173
"maxGrams" : 5 ,
179
174
"foldDiacritics" : False ,
180
- },
181
- "writer" : {
182
- "type" : "document" ,
183
- "fields" : {
184
- "name" : {
185
- "type" : "autocomplete" ,
186
- "analyzer" : "lucene.standard" ,
187
- "tokenization" : "edgeGram" ,
188
- "minGrams" : 3 ,
189
- "maxGrams" : 5 ,
190
- "foldDiacritics" : False ,
191
- }
192
- },
193
- },
175
+ }
194
176
},
195
- }
177
+ },
196
178
},
197
179
)
198
180
@@ -253,7 +235,7 @@ def setUpClass(cls):
253
235
cls .create_search_index (
254
236
Article ,
255
237
"exists_body_index" ,
256
- {"mappings" : { "dynamic" : False , "fields" : { " body" : {"type" : "token" }} }},
238
+ {"body" : {"type" : "token" }},
257
239
)
258
240
259
241
def setUp (self ):
@@ -282,7 +264,7 @@ def setUpClass(cls):
282
264
cls .create_search_index (
283
265
Article ,
284
266
"in_headline_index" ,
285
- {"mappings" : { "dynamic" : False , "fields" : { " headline" : {"type" : "token" }} }},
267
+ {"headline" : {"type" : "token" }},
286
268
)
287
269
288
270
def setUp (self ):
@@ -316,7 +298,7 @@ def setUpClass(cls):
316
298
cls .create_search_index (
317
299
Article ,
318
300
"phrase_body_index" ,
319
- {"mappings" : { "dynamic" : False , "fields" : { " body" : {"type" : "string" }} }},
301
+ {"body" : {"type" : "string" }},
320
302
)
321
303
322
304
def setUp (self ):
@@ -356,13 +338,8 @@ def setUpClass(cls):
356
338
Article ,
357
339
"query_string_index" ,
358
340
{
359
- "mappings" : {
360
- "dynamic" : False ,
361
- "fields" : {
362
- "headline" : {"type" : "string" },
363
- "body" : {"type" : "string" },
364
- },
365
- }
341
+ "headline" : {"type" : "string" },
342
+ "body" : {"type" : "string" },
366
343
},
367
344
)
368
345
@@ -416,7 +393,7 @@ def setUpClass(cls):
416
393
cls .create_search_index (
417
394
Article ,
418
395
"range_number_index" ,
419
- {"mappings" : { "dynamic" : False , "fields" : { " number" : {"type" : "number" }} }},
396
+ {"number" : {"type" : "number" }},
420
397
)
421
398
Article .objects .create (headline = "x" , number = 5 , body = "z" )
422
399
@@ -453,12 +430,7 @@ def setUpClass(cls):
453
430
cls .create_search_index (
454
431
Article ,
455
432
"regex_headline_index" ,
456
- {
457
- "mappings" : {
458
- "dynamic" : False ,
459
- "fields" : {"headline" : {"type" : "string" , "analyzer" : "lucene.keyword" }},
460
- }
461
- },
433
+ {"headline" : {"type" : "string" , "analyzer" : "lucene.keyword" }},
462
434
)
463
435
464
436
def setUp (self ):
@@ -498,7 +470,7 @@ def setUpClass(cls):
498
470
cls .create_search_index (
499
471
Article ,
500
472
"text_body_index" ,
501
- {"mappings" : { "dynamic" : False , "fields" : { " body" : {"type" : "string" }} }},
473
+ {"body" : {"type" : "string" }},
502
474
)
503
475
504
476
def setUp (self ):
@@ -560,12 +532,7 @@ def setUpClass(cls):
560
532
cls .create_search_index (
561
533
Article ,
562
534
"wildcard_headline_index" ,
563
- {
564
- "mappings" : {
565
- "dynamic" : False ,
566
- "fields" : {"headline" : {"type" : "string" , "analyzer" : "lucene.keyword" }},
567
- }
568
- },
535
+ {"headline" : {"type" : "string" , "analyzer" : "lucene.keyword" }},
569
536
)
570
537
571
538
def setUp (self ):
@@ -603,12 +570,7 @@ def setUpClass(cls):
603
570
cls .create_search_index (
604
571
Article ,
605
572
"geoshape_location_index" ,
606
- {
607
- "mappings" : {
608
- "dynamic" : False ,
609
- "fields" : {"location" : {"type" : "geo" , "indexShapes" : True }},
610
- }
611
- },
573
+ {"location" : {"type" : "geo" , "indexShapes" : True }},
612
574
)
613
575
614
576
def setUp (self ):
@@ -668,7 +630,7 @@ def setUpClass(cls):
668
630
cls .create_search_index (
669
631
Article ,
670
632
"geowithin_location_index" ,
671
- {"mappings" : { "dynamic" : False , "fields" : { " location" : {"type" : "geo" }} }},
633
+ {"location" : {"type" : "geo" }},
672
634
)
673
635
674
636
def setUp (self ):
@@ -743,12 +705,7 @@ def setUpClass(cls):
743
705
cls .create_search_index (
744
706
Article ,
745
707
"mlt_index" ,
746
- {
747
- "mappings" : {
748
- "dynamic" : False ,
749
- "fields" : {"body" : {"type" : "string" }, "headline" : {"type" : "string" }},
750
- }
751
- },
708
+ {"body" : {"type" : "string" }, "headline" : {"type" : "string" }},
752
709
)
753
710
cls .article1 = Article .objects .create (
754
711
headline = "Space exploration" , number = 1 , body = "Webb telescope"
@@ -782,14 +739,9 @@ def setUpClass(cls):
782
739
Article ,
783
740
"compound_index" ,
784
741
{
785
- "mappings" : {
786
- "dynamic" : False ,
787
- "fields" : {
788
- "headline" : [{"type" : "token" }, {"type" : "string" }],
789
- "body" : {"type" : "string" },
790
- "number" : {"type" : "number" },
791
- },
792
- }
742
+ "headline" : [{"type" : "token" }, {"type" : "string" }],
743
+ "body" : {"type" : "string" },
744
+ "number" : {"type" : "number" },
793
745
},
794
746
)
795
747
@@ -962,26 +914,20 @@ def test_str_returns_expected_format(self):
962
914
class SearchVectorTests (SearchUtilsMixin ):
963
915
@classmethod
964
916
def setUpClass (cls ):
965
- cls .create_search_index (
966
- Article ,
967
- "vector_index" ,
968
- {
969
- "fields" : [
970
- {
971
- "type" : "vector" ,
972
- "path" : "plot_embedding" ,
973
- "numDimensions" : 3 ,
974
- "similarity" : "cosine" ,
975
- "quantization" : "scalar" ,
976
- },
977
- {
978
- "type" : "filter" ,
979
- "path" : "number" ,
980
- },
981
- ]
982
- },
983
- type = "vectorSearch" ,
917
+ model = Article
918
+ idx = VectorSearchIndex (
919
+ fields = ["plot_embedding" , "number" ],
920
+ name = "vector_index" ,
921
+ similarities = "cosine" ,
984
922
)
923
+ with connection .schema_editor () as editor :
924
+ editor .add_index (model , idx )
925
+
926
+ def drop_index ():
927
+ with connection .schema_editor () as editor :
928
+ editor .remove_index (model , idx )
929
+
930
+ cls .addClassCleanup (drop_index )
985
931
986
932
def setUp (self ):
987
933
self .mars = Article .objects .create (
0 commit comments