Add missing integration tests for delete by ID API in vector store implementations.

Extract common vector store delete tests to base class

This commit extracts shared delete operation tests into a reusable BaseVectorStoreTests class.
This reduces code duplication and provides a consistent test suite for delete operations across
different vector store implementations. The base class includes tests for:

Deleting by ID
Deleting by filter expressions
Deleting by string filter expressions

Most of the vector store implementation now extends this base class and inherits these
common tests while maintaining the ability to add vector store specific tests.

Adding javadoc

Signed-off-by: Soby Chacko <soby.chacko@broadcom.com>
This commit is contained in:
Soby Chacko
2025-02-10 17:25:06 -05:00
committed by Ilayaperumal Gopinathan
parent a8e305d28a
commit 4d692a542b
17 changed files with 380 additions and 868 deletions

View File

@@ -24,6 +24,7 @@ import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -45,6 +46,7 @@ import org.springframework.ai.document.Document;
import org.springframework.ai.embedding.EmbeddingModel;
import org.springframework.ai.openai.OpenAiEmbeddingModel;
import org.springframework.ai.openai.api.OpenAiApi;
import org.springframework.ai.test.vectorstore.BaseVectorStoreTests;
import org.springframework.ai.vectorstore.SearchRequest;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.ai.vectorstore.filter.Filter;
@@ -71,7 +73,7 @@ import static org.assertj.core.api.Assertions.assertThat;
*/
@Testcontainers
@EnabledIfEnvironmentVariable(named = "OPENAI_API_KEY", matches = ".+")
public class MariaDBStoreIT {
public class MariaDBStoreIT extends BaseVectorStoreTests {
private static String schemaName = "testdb";
@@ -141,6 +143,14 @@ public class MariaDBStoreIT {
return true;
}
@Override
protected void executeTest(Consumer<VectorStore> testFunction) {
contextRunner.run(context -> {
VectorStore vectorStore = context.getBean(VectorStore.class);
testFunction.accept(vectorStore);
});
}
@ParameterizedTest(name = "{0} : {displayName} ")
@ValueSource(strings = { "COSINE", "EUCLIDEAN" })
public void addAndSearch(String distanceType) {
@@ -362,72 +372,6 @@ public class MariaDBStoreIT {
});
}
@Test
public void deleteByFilter() {
this.contextRunner.withPropertyValues("test.spring.ai.vectorstore.mariadb.distanceType=COSINE").run(context -> {
VectorStore vectorStore = context.getBean(VectorStore.class);
var bgDocument = new Document("The World is Big and Salvation Lurks Around the Corner",
Map.of("country", "BG", "year", 2020));
var nlDocument = new Document("The World is Big and Salvation Lurks Around the Corner",
Map.of("country", "NL", "year", 2021));
var bgDocument2 = new Document("The World is Big and Salvation Lurks Around the Corner",
Map.of("country", "BG", "year", 2023));
vectorStore.add(List.of(bgDocument, nlDocument, bgDocument2));
SearchRequest searchRequest = SearchRequest.builder()
.query("The World")
.topK(5)
.similarityThresholdAll()
.build();
List<Document> results = vectorStore.similaritySearch(searchRequest);
assertThat(results).hasSize(3);
Filter.Expression filterExpression = new Filter.Expression(Filter.ExpressionType.EQ,
new Filter.Key("country"), new Filter.Value("BG"));
vectorStore.delete(filterExpression);
// Verify deletion - should only have NL document remaining
results = vectorStore.similaritySearch(searchRequest);
assertThat(results).hasSize(1);
assertThat(results.get(0).getMetadata()).containsEntry("country", "NL");
dropTable(context);
});
}
@Test
public void deleteWithStringFilterExpression() {
this.contextRunner.withPropertyValues("test.spring.ai.vectorstore.mariadb.distanceType=COSINE").run(context -> {
VectorStore vectorStore = context.getBean(VectorStore.class);
var bgDocument = new Document("The World is Big and Salvation Lurks Around the Corner",
Map.of("country", "BG", "year", 2020));
var nlDocument = new Document("The World is Big and Salvation Lurks Around the Corner",
Map.of("country", "NL", "year", 2021));
var bgDocument2 = new Document("The World is Big and Salvation Lurks Around the Corner",
Map.of("country", "BG", "year", 2023));
vectorStore.add(List.of(bgDocument, nlDocument, bgDocument2));
var searchRequest = SearchRequest.builder().query("The World").topK(5).similarityThresholdAll().build();
List<Document> results = vectorStore.similaritySearch(searchRequest);
assertThat(results).hasSize(3);
vectorStore.delete("country == 'BG'");
results = vectorStore.similaritySearch(searchRequest);
assertThat(results).hasSize(1);
assertThat(results.get(0).getMetadata()).containsEntry("country", "NL");
dropTable(context);
});
}
@Test
public void deleteWithComplexFilterExpression() {
this.contextRunner.withPropertyValues("test.spring.ai.vectorstore.mariadb.distanceType=COSINE").run(context -> {