78
78
import com .mongodb .client .MongoClient ;
79
79
import com .mongodb .client .MongoClients ;
80
80
import com .mongodb .client .MongoCollection ;
81
+ import com .mongodb .client .MongoCursor ;
81
82
import com .mongodb .client .model .IndexOptions ;
82
83
import com .mongodb .client .model .SearchIndexModel ;
83
84
import com .mongodb .client .model .SearchIndexType ;
@@ -120,28 +121,49 @@ static void beforeAll() throws InterruptedException {
120
121
userCollection .createIndex (new Document ("location.coordinates" , "2d" ), new IndexOptions ());
121
122
userCollection .createIndex (new Document ("location.coordinates" , "2dsphere" ), new IndexOptions ());
122
123
124
+ Thread .sleep (250 ); // just wait a little or the index will be broken
125
+ }
126
+
127
+ /**
128
+ * Create the vector search index and wait till it is queryable and actually serving data. Since this may slow down
129
+ * tests quite a bit, better call it only when needed to run certain tests.
130
+ */
131
+ private static void initializeVectorIndex () {
132
+
133
+ String indexName = "embedding.vector_cos" ;
134
+
123
135
Document searchIndex = new Document ("fields" ,
124
136
List .of (new Document ("type" , "vector" ).append ("path" , "embedding" ).append ("numDimensions" , 5 )
125
137
.append ("similarity" , "cosine" ), new Document ("type" , "filter" ).append ("path" , "last_name" )));
126
138
127
- userCollection .createSearchIndexes (List .of (
128
- new SearchIndexModel ("embedding.vector_cos" , searchIndex , SearchIndexType .of (new BsonString ("vectorSearch" )))));
139
+ MongoCollection <Document > userCollection = client .getDatabase (DB_NAME ).getCollection (COLLECTION_NAME );
140
+ userCollection .createSearchIndexes (
141
+ List .of (new SearchIndexModel (indexName , searchIndex , SearchIndexType .of (new BsonString ("vectorSearch" )))));
129
142
143
+ // wait for search index to be queryable
130
144
Awaitility .await ().atMost (Duration .ofSeconds (120 )).pollInterval (Duration .ofMillis (200 )).until (() -> {
131
145
132
146
List <Document > execute = userCollection
133
- .aggregate (
134
- List .of (Document .parse ("{'$listSearchIndexes': { 'name' : '%s'}}" .formatted ("embedding.vector_cos" ))))
147
+ .aggregate (List .of (Document .parse ("{'$listSearchIndexes': { 'name' : '%s'}}" .formatted (indexName ))))
135
148
.into (new ArrayList <>());
136
149
for (Document doc : execute ) {
137
- if (doc .getString ("name" ).equals ("embedding.vector_cos" )) {
150
+ if (doc .getString ("name" ).equals (indexName )) {
138
151
return doc .getString ("status" ).equals ("READY" );
139
152
}
140
153
}
141
154
return false ;
142
155
});
143
156
144
- Thread .sleep (250 ); // just wait a little or the index will be broken
157
+ Document $vectorSearch = new Document ("$vectorSearch" ,
158
+ new Document ("index" , indexName ).append ("limit" , 1 ).append ("numCandidates" , 20 ).append ("path" , "embedding" )
159
+ .append ("queryVector" , List .of (1.0 , 1.12345 , 2.23456 , 3.34567 , 4.45678 )));
160
+
161
+ // wait for search index to serve data
162
+ Awaitility .await ().atMost (Duration .ofSeconds (120 )).pollInterval (Duration .ofMillis (200 )).until (() -> {
163
+ try (MongoCursor <Document > cursor = userCollection .aggregate (List .of ($vectorSearch )).iterator ()) {
164
+ return cursor .hasNext ();
165
+ }
166
+ });
145
167
}
146
168
147
169
@ BeforeEach
@@ -790,9 +812,9 @@ void testNearReturningGeoPage() {
790
812
}
791
813
792
814
@ Test
793
- void vectorSearchFromAnnotation () throws InterruptedException {
815
+ void vectorSearchFromAnnotation () {
794
816
795
- Thread . sleep ( 1000 ); // srly - reindex for vector search
817
+ initializeVectorIndex ();
796
818
797
819
Vector vector = Vector .of (1.00000d , 1.12345d , 2.23456d , 3.34567d , 4.45678d );
798
820
SearchResults <User > results = fragment .annotatedVectorSearch ("Skywalker" , vector , Score .of (0.99 ), Limit .of (10 ));
@@ -801,9 +823,9 @@ void vectorSearchFromAnnotation() throws InterruptedException {
801
823
}
802
824
803
825
@ Test
804
- void vectorSearchWithDerivedQuery () throws InterruptedException {
826
+ void vectorSearchWithDerivedQuery () {
805
827
806
- Thread . sleep ( 1000 ); // srly - reindex for vector search
828
+ initializeVectorIndex ();
807
829
808
830
Vector vector = Vector .of (1.00000d , 1.12345d , 2.23456d , 3.34567d , 4.45678d );
809
831
SearchResults <User > results = fragment .searchCosineByLastnameAndEmbeddingNear ("Skywalker" , vector , Score .of (0.98 ),
@@ -813,9 +835,9 @@ void vectorSearchWithDerivedQuery() throws InterruptedException {
813
835
}
814
836
815
837
@ Test
816
- void vectorSearchReturningResultsAsList () throws InterruptedException {
838
+ void vectorSearchReturningResultsAsList () {
817
839
818
- Thread . sleep ( 1000 ); // srly - reindex for vector search
840
+ initializeVectorIndex ();
819
841
820
842
Vector vector = Vector .of (1.00000d , 1.12345d , 2.23456d , 3.34567d , 4.45678d );
821
843
List <User > results = fragment .searchAsListByLastnameAndEmbeddingNear ("Skywalker" , vector , Limit .of (10 ));
@@ -824,9 +846,9 @@ void vectorSearchReturningResultsAsList() throws InterruptedException {
824
846
}
825
847
826
848
@ Test
827
- void vectorSearchWithLimitFromAnnotation () throws InterruptedException {
849
+ void vectorSearchWithLimitFromAnnotation () {
828
850
829
- Thread . sleep ( 1000 ); // srly - reindex for vector search
851
+ initializeVectorIndex ();
830
852
831
853
Vector vector = Vector .of (1.00000d , 1.12345d , 2.23456d , 3.34567d , 4.45678d );
832
854
SearchResults <User > results = fragment .searchByLastnameAndEmbeddingWithin ("Skywalker" , vector ,
@@ -836,9 +858,9 @@ void vectorSearchWithLimitFromAnnotation() throws InterruptedException {
836
858
}
837
859
838
860
@ Test
839
- void vectorSearchWithSorting () throws InterruptedException {
861
+ void vectorSearchWithSorting () {
840
862
841
- Thread . sleep ( 1000 ); // srly - reindex for vector search
863
+ initializeVectorIndex ();
842
864
843
865
Vector vector = Vector .of (1.00000d , 1.12345d , 2.23456d , 3.34567d , 4.45678d );
844
866
SearchResults <User > results = fragment .searchByLastnameAndEmbeddingWithinOrderByFirstname ("Skywalker" , vector ,
@@ -848,9 +870,9 @@ void vectorSearchWithSorting() throws InterruptedException {
848
870
}
849
871
850
872
@ Test
851
- void vectorSearchWithLimitFromDerivedQuery () throws InterruptedException {
873
+ void vectorSearchWithLimitFromDerivedQuery () {
852
874
853
- Thread . sleep ( 1000 ); // srly - reindex for vector search
875
+ initializeVectorIndex ();
854
876
855
877
Vector vector = Vector .of (1.00000d , 1.12345d , 2.23456d , 3.34567d , 4.45678d );
856
878
SearchResults <User > results = fragment .searchTop1ByLastnameAndEmbeddingWithin ("Skywalker" , vector ,
0 commit comments