Skip to content

Commit 4e58d13

Browse files
Smart wait for search index to become available
1 parent 88fc955 commit 4e58d13

File tree

1 file changed

+40
-18
lines changed

1 file changed

+40
-18
lines changed

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/aot/MongoRepositoryContributorTests.java

Lines changed: 40 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@
7878
import com.mongodb.client.MongoClient;
7979
import com.mongodb.client.MongoClients;
8080
import com.mongodb.client.MongoCollection;
81+
import com.mongodb.client.MongoCursor;
8182
import com.mongodb.client.model.IndexOptions;
8283
import com.mongodb.client.model.SearchIndexModel;
8384
import com.mongodb.client.model.SearchIndexType;
@@ -120,28 +121,49 @@ static void beforeAll() throws InterruptedException {
120121
userCollection.createIndex(new Document("location.coordinates", "2d"), new IndexOptions());
121122
userCollection.createIndex(new Document("location.coordinates", "2dsphere"), new IndexOptions());
122123

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+
123135
Document searchIndex = new Document("fields",
124136
List.of(new Document("type", "vector").append("path", "embedding").append("numDimensions", 5)
125137
.append("similarity", "cosine"), new Document("type", "filter").append("path", "last_name")));
126138

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")))));
129142

143+
// wait for search index to be queryable
130144
Awaitility.await().atMost(Duration.ofSeconds(120)).pollInterval(Duration.ofMillis(200)).until(() -> {
131145

132146
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))))
135148
.into(new ArrayList<>());
136149
for (Document doc : execute) {
137-
if (doc.getString("name").equals("embedding.vector_cos")) {
150+
if (doc.getString("name").equals(indexName)) {
138151
return doc.getString("status").equals("READY");
139152
}
140153
}
141154
return false;
142155
});
143156

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+
});
145167
}
146168

147169
@BeforeEach
@@ -790,9 +812,9 @@ void testNearReturningGeoPage() {
790812
}
791813

792814
@Test
793-
void vectorSearchFromAnnotation() throws InterruptedException {
815+
void vectorSearchFromAnnotation() {
794816

795-
Thread.sleep(1000); // srly - reindex for vector search
817+
initializeVectorIndex();
796818

797819
Vector vector = Vector.of(1.00000d, 1.12345d, 2.23456d, 3.34567d, 4.45678d);
798820
SearchResults<User> results = fragment.annotatedVectorSearch("Skywalker", vector, Score.of(0.99), Limit.of(10));
@@ -801,9 +823,9 @@ void vectorSearchFromAnnotation() throws InterruptedException {
801823
}
802824

803825
@Test
804-
void vectorSearchWithDerivedQuery() throws InterruptedException {
826+
void vectorSearchWithDerivedQuery() {
805827

806-
Thread.sleep(1000); // srly - reindex for vector search
828+
initializeVectorIndex();
807829

808830
Vector vector = Vector.of(1.00000d, 1.12345d, 2.23456d, 3.34567d, 4.45678d);
809831
SearchResults<User> results = fragment.searchCosineByLastnameAndEmbeddingNear("Skywalker", vector, Score.of(0.98),
@@ -813,9 +835,9 @@ void vectorSearchWithDerivedQuery() throws InterruptedException {
813835
}
814836

815837
@Test
816-
void vectorSearchReturningResultsAsList() throws InterruptedException {
838+
void vectorSearchReturningResultsAsList() {
817839

818-
Thread.sleep(1000); // srly - reindex for vector search
840+
initializeVectorIndex();
819841

820842
Vector vector = Vector.of(1.00000d, 1.12345d, 2.23456d, 3.34567d, 4.45678d);
821843
List<User> results = fragment.searchAsListByLastnameAndEmbeddingNear("Skywalker", vector, Limit.of(10));
@@ -824,9 +846,9 @@ void vectorSearchReturningResultsAsList() throws InterruptedException {
824846
}
825847

826848
@Test
827-
void vectorSearchWithLimitFromAnnotation() throws InterruptedException {
849+
void vectorSearchWithLimitFromAnnotation() {
828850

829-
Thread.sleep(1000); // srly - reindex for vector search
851+
initializeVectorIndex();
830852

831853
Vector vector = Vector.of(1.00000d, 1.12345d, 2.23456d, 3.34567d, 4.45678d);
832854
SearchResults<User> results = fragment.searchByLastnameAndEmbeddingWithin("Skywalker", vector,
@@ -836,9 +858,9 @@ void vectorSearchWithLimitFromAnnotation() throws InterruptedException {
836858
}
837859

838860
@Test
839-
void vectorSearchWithSorting() throws InterruptedException {
861+
void vectorSearchWithSorting() {
840862

841-
Thread.sleep(1000); // srly - reindex for vector search
863+
initializeVectorIndex();
842864

843865
Vector vector = Vector.of(1.00000d, 1.12345d, 2.23456d, 3.34567d, 4.45678d);
844866
SearchResults<User> results = fragment.searchByLastnameAndEmbeddingWithinOrderByFirstname("Skywalker", vector,
@@ -848,9 +870,9 @@ void vectorSearchWithSorting() throws InterruptedException {
848870
}
849871

850872
@Test
851-
void vectorSearchWithLimitFromDerivedQuery() throws InterruptedException {
873+
void vectorSearchWithLimitFromDerivedQuery() {
852874

853-
Thread.sleep(1000); // srly - reindex for vector search
875+
initializeVectorIndex();
854876

855877
Vector vector = Vector.of(1.00000d, 1.12345d, 2.23456d, 3.34567d, 4.45678d);
856878
SearchResults<User> results = fragment.searchTop1ByLastnameAndEmbeddingWithin("Skywalker", vector,

0 commit comments

Comments
 (0)