Skip to content

Commit 868e288

Browse files
sobychackomarkpollack
authored andcommitted
GH-1949: Align CassandraVectorStore API naming with other vector stores
Fixes: #1949 - Rename 'disallowSchemaChanges(boolean)' to 'initializeSchema(boolean)' for consistency with other vector store implementations - Maintain semantic meaning by inverting the default value (from disallowSchemaChanges=false to initializeSchema=true) in the CassandraVectorStore implementation - Keep default behavior in auto-configuration consistent with other vector stores - Remove unused 'returnEmbeddings' functionality and related code - Update test cases to use the new initialization parameter - Ref docs and javadocs updates This change improves API consistency across Spring AI vector stores while preserving the same behavior in the Cassandra implementation. Signed-off-by: Soby Chacko <soby.chacko@broadcom.com>
1 parent 848a3fd commit 868e288

File tree

7 files changed

+33
-94
lines changed

7 files changed

+33
-94
lines changed

auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-cassandra/src/main/java/org/springframework/ai/vectorstore/cassandra/autoconfigure/CassandraVectorStoreAutoConfiguration.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,7 @@ public CassandraVectorStore vectorStore(EmbeddingModel embeddingModel, Cassandra
7474
.embeddingColumnName(properties.getEmbeddingColumnName())
7575
.indexName(properties.getIndexName())
7676
.fixedThreadPoolExecutorSize(properties.getFixedThreadPoolExecutorSize())
77-
.disallowSchemaChanges(!properties.isInitializeSchema())
78-
.returnEmbeddings(properties.getReturnEmbeddings())
77+
.initializeSchema(properties.isInitializeSchema())
7978
.observationRegistry(observationRegistry.getIfUnique(() -> ObservationRegistry.NOOP))
8079
.customObservationConvention(customObservationConvention.getIfAvailable(() -> null))
8180
.batchingStrategy(batchingStrategy)

auto-configurations/vector-stores/spring-ai-autoconfigure-vector-store-cassandra/src/main/java/org/springframework/ai/vectorstore/cassandra/autoconfigure/CassandraVectorStoreProperties.java

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,6 @@
1616

1717
package org.springframework.ai.vectorstore.cassandra.autoconfigure;
1818

19-
import org.slf4j.Logger;
20-
import org.slf4j.LoggerFactory;
21-
2219
import org.springframework.ai.vectorstore.cassandra.CassandraVectorStore;
2320
import org.springframework.ai.vectorstore.properties.CommonVectorStoreProperties;
2421
import org.springframework.boot.context.properties.ConfigurationProperties;
@@ -35,8 +32,6 @@ public class CassandraVectorStoreProperties extends CommonVectorStoreProperties
3532

3633
public static final String CONFIG_PREFIX = "spring.ai.vectorstore.cassandra";
3734

38-
private static final Logger logger = LoggerFactory.getLogger(CassandraVectorStoreProperties.class);
39-
4035
private String keyspace = CassandraVectorStore.DEFAULT_KEYSPACE_NAME;
4136

4237
private String table = CassandraVectorStore.DEFAULT_TABLE_NAME;
@@ -47,8 +42,6 @@ public class CassandraVectorStoreProperties extends CommonVectorStoreProperties
4742

4843
private String embeddingColumnName = CassandraVectorStore.DEFAULT_EMBEDDING_COLUMN_NAME;
4944

50-
private boolean returnEmbeddings = false;
51-
5245
private int fixedThreadPoolExecutorSize = CassandraVectorStore.DEFAULT_ADD_CONCURRENCY;
5346

5447
public String getKeyspace() {
@@ -91,14 +84,6 @@ public void setEmbeddingColumnName(String embeddingColumnName) {
9184
this.embeddingColumnName = embeddingColumnName;
9285
}
9386

94-
public boolean getReturnEmbeddings() {
95-
return this.returnEmbeddings;
96-
}
97-
98-
public void setReturnEmbeddings(boolean returnEmbeddings) {
99-
this.returnEmbeddings = returnEmbeddings;
100-
}
101-
10287
public int getFixedThreadPoolExecutorSize() {
10388
return this.fixedThreadPoolExecutorSize;
10489
}

spring-ai-docs/src/main/antora/modules/ROOT/pages/api/vectordbs/apache-cassandra.adoc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ This Spring AI Vector Store is designed to work for both brand-new RAG applicati
2020

2121
The store can also be used for non-RAG use-cases in an existing database, e.g. semantic searches, geo-proximity searches, etc.
2222

23-
The store will automatically create, or enhance, the schema as needed according to its configuration. If you don't want the schema modifications, configure the store with `disallowSchemaChanges`.
23+
The store will automatically create, or enhance, the schema as needed according to its configuration. If you don't want the schema modifications, configure the store with `initializeSchema`.
2424

25-
When using spring-boot-autoconfigure `disallowSchemaChanges` defaults to true, per Spring Boot standards, and you must opt-in to schema creation/modifications by setting `...initialize-schema=true` in the `application.properties` file.
25+
When using spring-boot-autoconfigure `initializeSchema` defaults to `false`, per Spring Boot standards, and you must opt-in to schema creation/modifications by setting `...initialize-schema=true` in the `application.properties` file.
2626

2727
== What is JVector?
2828

@@ -167,7 +167,7 @@ public VectorStore vectorStore(CqlSession session, EmbeddingModel embeddingModel
167167
// Performance tuning
168168
.fixedThreadPoolExecutorSize(32)
169169
// Schema management
170-
.disallowSchemaChanges(false)
170+
.initializeSchema(true)
171171
// Custom batching strategy
172172
.batchingStrategy(new TokenCountBatchingStrategy())
173173
.build();
@@ -282,7 +282,7 @@ public VectorStore vectorStore(CqlSession session, EmbeddingModel embeddingModel
282282
.contentColumnName("body")
283283
.embeddingColumnName("all_minilm_l6_v2_embedding")
284284
.indexName("all_minilm_l6_v2_ann")
285-
.disallowSchemaChanges(true)
285+
.initializeSchema(false)
286286
.addMetadataColumns(extraColumns)
287287
.primaryKeyTranslator((List<Object> primaryKeys) -> {
288288
if (primaryKeys.isEmpty()) {

vector-stores/spring-ai-cassandra-store/src/main/java/org/springframework/ai/vectorstore/cassandra/CassandraVectorStore.java

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@
9595
*
9696
* A schema matching the configuration is automatically created if it doesn't exist.
9797
* Missing columns and indexes in existing tables will also be automatically created.
98-
* Disable this with the CassandraBuilder#disallowSchemaChanges().
98+
* Disable this with the CassandraBuilder#initializeSchema(boolean) method().
9999
*
100100
* <p>
101101
* Basic usage example:
@@ -139,7 +139,7 @@
139139
* .contentColumnName("text")
140140
* .embeddingColumnName("vector")
141141
* .fixedThreadPoolExecutorSize(32)
142-
* .disallowSchemaChanges(false)
142+
* .initializeSchema(true)
143143
* .batchingStrategy(new TokenCountBatchingStrategy())
144144
* .build();
145145
* }</pre>
@@ -202,7 +202,7 @@ public class CassandraVectorStore extends AbstractObservationVectorStore impleme
202202

203203
private final Schema schema;
204204

205-
private final boolean disallowSchemaChanges;
205+
private final boolean initializeSchema;
206206

207207
private final FilterExpressionConverter filterExpressionConverter;
208208

@@ -229,7 +229,7 @@ protected CassandraVectorStore(Builder builder) {
229229

230230
this.session = builder.session;
231231
this.schema = builder.buildSchema();
232-
this.disallowSchemaChanges = builder.disallowSchemaChanges;
232+
this.initializeSchema = builder.initializeSchema;
233233
this.documentIdTranslator = builder.documentIdTranslator;
234234
this.primaryKeyTranslator = builder.primaryKeyTranslator;
235235
this.executor = Executors.newFixedThreadPool(builder.fixedThreadPoolExecutorSize);
@@ -525,7 +525,7 @@ static void dropKeyspace(Builder builder) {
525525
}
526526

527527
void ensureSchemaExists(int vectorDimension) {
528-
if (!this.disallowSchemaChanges) {
528+
if (this.initializeSchema) {
529529
SchemaUtil.ensureKeyspaceExists(this.session, this.schema.keyspace);
530530
ensureTableExists(vectorDimension);
531531
ensureTableColumnsExist(vectorDimension);
@@ -805,7 +805,7 @@ public static class Builder extends AbstractVectorStoreBuilder<Builder> {
805805

806806
private Set<SchemaColumn> metadataColumns = new HashSet<>();
807807

808-
private boolean disallowSchemaChanges = false;
808+
private boolean initializeSchema = true;
809809

810810
private int fixedThreadPoolExecutorSize = DEFAULT_ADD_CONCURRENCY;
811811

@@ -821,8 +821,6 @@ public static class Builder extends AbstractVectorStoreBuilder<Builder> {
821821
return (String) primaryKeyColumns.get(0);
822822
};
823823

824-
private boolean returnEmbeddings = false;
825-
826824
private Builder(EmbeddingModel embeddingModel) {
827825
super(embeddingModel);
828826
}
@@ -938,12 +936,12 @@ public Builder indexName(String indexName) {
938936
}
939937

940938
/**
941-
* Sets whether to disallow schema changes.
942-
* @param disallowSchemaChanges true to disallow schema changes
939+
* Sets whether to initialize the schema.
940+
* @param initializeSchema true to initialize schema, false otherwise
943941
* @return the builder instance
944942
*/
945-
public Builder disallowSchemaChanges(boolean disallowSchemaChanges) {
946-
this.disallowSchemaChanges = disallowSchemaChanges;
943+
public Builder initializeSchema(boolean initializeSchema) {
944+
this.initializeSchema = initializeSchema;
947945
return this;
948946
}
949947

@@ -1016,11 +1014,6 @@ public Builder primaryKeyTranslator(PrimaryKeyTranslator translator) {
10161014
return this;
10171015
}
10181016

1019-
public Builder returnEmbeddings(boolean returnEmbeddings) {
1020-
this.returnEmbeddings = true;
1021-
return this;
1022-
}
1023-
10241017
Schema buildSchema() {
10251018
if (this.indexName == null) {
10261019
this.indexName = String.format("%s_%s_%s", this.table, this.embeddingColumnName, DEFAULT_INDEX_SUFFIX);

vector-stores/spring-ai-cassandra-store/src/test/java/org/springframework/ai/vectorstore/cassandra/CassandraRichSchemaVectorStoreIT.java

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ static CassandraVectorStore.Builder storeBuilder(ApplicationContext context,
150150
@Test
151151
void ensureSchemaCreation() {
152152
this.contextRunner.run(context -> {
153-
try (CassandraVectorStore store = createStore(context, false)) {
153+
try (CassandraVectorStore store = createStore(context, true)) {
154154
Assertions.assertNotNull(store);
155155
store.checkSchemaValid();
156156
store.similaritySearch(SearchRequest.builder().query("1843").topK(1).build());
@@ -162,7 +162,7 @@ void ensureSchemaCreation() {
162162
void ensureSchemaNoCreation() {
163163
this.contextRunner.run(context -> {
164164
executeCqlFile(context, "test_wiki_full_schema.cql");
165-
var builder = createBuilder(context, List.of(), true, false);
165+
var builder = createBuilder(context, List.of(), false, false);
166166
Assertions.assertNotNull(builder);
167167
var store = new CassandraVectorStore(builder);
168168
try {
@@ -176,7 +176,7 @@ void ensureSchemaNoCreation() {
176176

177177
// IllegalStateException: column all_minilm_l6_v2_embedding does not exist
178178
IllegalStateException ise = Assertions.assertThrows(IllegalStateException.class,
179-
() -> createStore(context, List.of(), true, false));
179+
() -> createStore(context, List.of(), false, false));
180180

181181
Assertions.assertEquals("column all_minilm_l6_v2_embedding does not exist", ise.getMessage());
182182
}
@@ -193,7 +193,7 @@ void ensureSchemaPartialCreation() {
193193
int PARTIAL_FILES = 5;
194194
for (int i = 0; i < PARTIAL_FILES; ++i) {
195195
executeCqlFile(context, java.lang.String.format("test_wiki_partial_%d_schema.cql", i));
196-
var builder = createBuilder(context, List.of(), false, false);
196+
var builder = createBuilder(context, List.of(), true, false);
197197
Assertions.assertNotNull(builder);
198198
CassandraVectorStore.dropKeyspace(builder);
199199
var store = builder.build();
@@ -216,7 +216,7 @@ void ensureSchemaPartialCreation() {
216216
@Test
217217
void addAndSearch() {
218218
this.contextRunner.run(context -> {
219-
try (CassandraVectorStore store = createStore(context, false)) {
219+
try (CassandraVectorStore store = createStore(context, true)) {
220220
store.add(documents);
221221

222222
List<Document> results = store.similaritySearch(
@@ -290,7 +290,7 @@ void addAndSearchPoormansBench() {
290290
@Test
291291
void searchWithPartitionFilter() throws InterruptedException {
292292
this.contextRunner.run(context -> {
293-
try (CassandraVectorStore store = createStore(context, false)) {
293+
try (CassandraVectorStore store = createStore(context, true)) {
294294
store.add(documents);
295295

296296
List<Document> results = store
@@ -346,7 +346,7 @@ void searchWithPartitionFilter() throws InterruptedException {
346346
@Test
347347
void unsearchableFilters() throws InterruptedException {
348348
this.contextRunner.run(context -> {
349-
try (CassandraVectorStore store = createStore(context, false)) {
349+
try (CassandraVectorStore store = createStore(context, true)) {
350350
store.add(documents);
351351

352352
List<Document> results = store
@@ -367,7 +367,7 @@ void unsearchableFilters() throws InterruptedException {
367367
@Test
368368
void searchWithFilters() throws InterruptedException {
369369
this.contextRunner.run(context -> {
370-
try (CassandraVectorStore store = createStore(context, false)) {
370+
try (CassandraVectorStore store = createStore(context, true)) {
371371
store.add(documents);
372372

373373
List<Document> results = store
@@ -447,7 +447,7 @@ void searchWithFilterOnPrimaryKeys() throws InterruptedException {
447447
new SchemaColumn("title", DataTypes.TEXT, CassandraVectorStore.SchemaColumnTags.INDEXED),
448448
new SchemaColumn("chunk_no", DataTypes.INT, CassandraVectorStore.SchemaColumnTags.INDEXED));
449449

450-
try (CassandraVectorStore store = createStore(context, overrides, false, true)) {
450+
try (CassandraVectorStore store = createStore(context, overrides, true, true)) {
451451

452452
store.add(documents);
453453

@@ -481,7 +481,7 @@ void searchWithFilterOnPrimaryKeys() throws InterruptedException {
481481
@Test
482482
void documentUpdate() {
483483
this.contextRunner.run(context -> {
484-
try (CassandraVectorStore store = createStore(context, false)) {
484+
try (CassandraVectorStore store = createStore(context, true)) {
485485
store.add(documents);
486486

487487
List<Document> results = store
@@ -532,7 +532,7 @@ void documentUpdate() {
532532
@Test
533533
void searchWithThreshold() {
534534
this.contextRunner.run(context -> {
535-
try (CassandraVectorStore store = createStore(context, false)) {
535+
try (CassandraVectorStore store = createStore(context, true)) {
536536
store.add(documents);
537537

538538
List<Document> fullResult = store.similaritySearch(
@@ -562,19 +562,16 @@ void searchWithThreshold() {
562562
});
563563
}
564564

565-
private CassandraVectorStore createStore(ApplicationContext context, boolean disallowSchemaCreation)
566-
throws IOException {
565+
private CassandraVectorStore createStore(ApplicationContext context, boolean initializeSchema) throws IOException {
567566

568-
return createStore(context, List.of(), disallowSchemaCreation, true);
567+
return createStore(context, List.of(), initializeSchema, true);
569568
}
570569

571570
private CassandraVectorStore createStore(ApplicationContext context, List<SchemaColumn> columnOverrides,
572-
boolean disallowSchemaCreation, boolean dropKeyspaceFirst) throws IOException {
571+
boolean initializeSchema, boolean dropKeyspaceFirst) throws IOException {
573572

574573
CassandraVectorStore.Builder builder = storeBuilder(context, columnOverrides);
575-
if (disallowSchemaCreation) {
576-
builder = builder.disallowSchemaChanges(true);
577-
}
574+
builder.initializeSchema(initializeSchema);
578575

579576
if (dropKeyspaceFirst) {
580577
CassandraVectorStore.dropKeyspace(builder);
@@ -584,12 +581,10 @@ private CassandraVectorStore createStore(ApplicationContext context, List<Schema
584581
}
585582

586583
private CassandraVectorStore.Builder createBuilder(ApplicationContext context, List<SchemaColumn> columnOverrides,
587-
boolean disallowSchemaCreation, boolean dropKeyspaceFirst) throws IOException {
584+
boolean initailzeSchema, boolean dropKeyspaceFirst) throws IOException {
588585

589586
CassandraVectorStore.Builder builder = storeBuilder(context, columnOverrides);
590-
if (disallowSchemaCreation) {
591-
builder = builder.disallowSchemaChanges(true);
592-
}
587+
builder.initializeSchema(initailzeSchema);
593588

594589
if (dropKeyspaceFirst) {
595590
CassandraVectorStore.dropKeyspace(builder);

vector-stores/spring-ai-cassandra-store/src/test/java/org/springframework/ai/vectorstore/cassandra/CassandraVectorStoreIT.java

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -172,39 +172,6 @@ void addAndSearch() {
172172
});
173173
}
174174

175-
@Test
176-
void addAndSearchReturnEmbeddings() {
177-
this.contextRunner.run(context -> {
178-
CassandraVectorStore.Builder builder = storeBuilder(context.getBean(CqlSession.class),
179-
context.getBean(EmbeddingModel.class))
180-
.returnEmbeddings(true);
181-
182-
try (CassandraVectorStore store = createTestStore(context, builder)) {
183-
List<Document> documents = documents();
184-
store.add(documents);
185-
186-
List<Document> results = store
187-
.similaritySearch(SearchRequest.builder().query("Spring").topK(1).build());
188-
189-
assertThat(results).hasSize(1);
190-
Document resultDoc = results.get(0);
191-
assertThat(resultDoc.getId()).isEqualTo(documents().get(0).getId());
192-
193-
assertThat(resultDoc.getText()).contains(
194-
"Spring AI provides abstractions that serve as the foundation for developing AI applications.");
195-
196-
assertThat(resultDoc.getMetadata()).hasSize(1);
197-
assertThat(resultDoc.getMetadata()).containsKey(DocumentMetadata.DISTANCE.value());
198-
199-
// Remove all documents from the store
200-
store.delete(documents().stream().map(doc -> doc.getId()).toList());
201-
202-
results = store.similaritySearch(SearchRequest.builder().query("Spring").topK(1).build());
203-
assertThat(results).isEmpty();
204-
}
205-
});
206-
}
207-
208175
@Test
209176
void searchWithPartitionFilter() throws InterruptedException {
210177
this.contextRunner.run(context -> {

vector-stores/spring-ai-cassandra-store/src/test/java/org/springframework/ai/vectorstore/cassandra/WikiVectorStoreExample.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ public CassandraVectorStore store(CqlSession cqlSession, EmbeddingModel embeddin
102102
.contentColumnName("body")
103103
.embeddingColumnName("all_minilm_l6_v2_embedding")
104104
.indexName("all_minilm_l6_v2_ann")
105-
.disallowSchemaChanges(true)
105+
.initializeSchema(false)
106106
.addMetadataColumns(extraColumns)
107107
.primaryKeyTranslator((List<Object> primaryKeys) -> {
108108
// the deliminator used to join fields together into the document's id

0 commit comments

Comments
 (0)