Skip to content

Commit 254b863

Browse files
meistermeiertzolov
authored andcommitted
Allow configuration of vector index name.
At the moment, it is not possible to configure SpringAI to use an existing index in the database. This commit enables the user to provide the index name for auto configuration or builder usage.
1 parent dc04327 commit 254b863

File tree

4 files changed

+40
-6
lines changed

4 files changed

+40
-6
lines changed

spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/neo4j/Neo4jVectorStoreAutoConfiguration.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ public VectorStore vectorStore(Driver driver, EmbeddingClient embeddingClient,
5656
.withDistanceType(properties.getDistanceType())
5757
.withLabel(properties.getLabel())
5858
.withEmbeddingProperty(properties.getEmbeddingProperty())
59+
.withIndexName(properties.getIndexName())
5960
.build();
6061

6162
return new Neo4jVectorStore(driver, embeddingClient, config);

spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/vectorstore/neo4j/Neo4jVectorStoreProperties.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ public class Neo4jVectorStoreProperties {
3737

3838
private String embeddingProperty = Neo4jVectorStore.DEFAULT_EMBEDDING_PROPERTY;
3939

40+
private String indexName = Neo4jVectorStore.DEFAULT_INDEX_NAME;
41+
4042
public String getDatabaseName() {
4143
return databaseName;
4244
}
@@ -77,4 +79,12 @@ public void setEmbeddingProperty(String embeddingProperty) {
7779
this.embeddingProperty = embeddingProperty;
7880
}
7981

82+
public String getIndexName() {
83+
return this.indexName;
84+
}
85+
86+
public void setIndexName(String indexName) {
87+
this.indexName = indexName;
88+
}
89+
8090
}

spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/vectorstore/neo4j/Neo4jVectorStoreAutoConfigurationIT.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,13 @@ public class Neo4jVectorStoreAutoConfigurationIT {
6666
void addAndSearch() {
6767
contextRunner
6868
.withPropertyValues("spring.ai.vectorstore.neo4j.label=my_test_label",
69-
"spring.ai.vectorstore.neo4j.embeddingDimension=384")
69+
"spring.ai.vectorstore.neo4j.embeddingDimension=384",
70+
"spring.ai.vectorstore.neo4j.indexName=customIndexName")
7071
.run(context -> {
7172
var properties = context.getBean(Neo4jVectorStoreProperties.class);
7273
assertThat(properties.getLabel()).isEqualTo("my_test_label");
7374
assertThat(properties.getEmbeddingDimension()).isEqualTo(384);
75+
assertThat(properties.getIndexName()).isEqualTo("customIndexName");
7476

7577
VectorStore vectorStore = context.getBean(VectorStore.class);
7678
vectorStore.add(documents);

vector-stores/spring-ai-neo4j-store/src/main/java/org/springframework/ai/vectorstore/Neo4jVectorStore.java

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ public static final class Neo4jVectorStoreConfig {
6969

7070
private final String quotedLabel;
7171

72+
private final String indexName;
73+
7274
/**
7375
* Start building a new configuration.
7476
* @return The entry point for creating a new configuration.
@@ -97,6 +99,7 @@ private Neo4jVectorStoreConfig(Builder builder) {
9799
this.label = builder.label;
98100
this.embeddingProperty = builder.embeddingProperty;
99101
this.quotedLabel = SchemaNames.sanitize(this.label).orElseThrow();
102+
this.indexName = builder.indexName;
100103
}
101104

102105
public static class Builder {
@@ -111,6 +114,8 @@ public static class Builder {
111114

112115
private String embeddingProperty = DEFAULT_EMBEDDING_PROPERTY;
113116

117+
private String indexName = DEFAULT_INDEX_NAME;
118+
114119
private Builder() {
115120
}
116121

@@ -182,6 +187,21 @@ public Builder withEmbeddingProperty(String newEmbeddingProperty) {
182187
return this;
183188
}
184189

190+
/**
191+
* Configures the vector index to be used. Defaults to
192+
* {@literal spring-ai-document-index}.
193+
* @param newIndexName The name of the index to be used for storing and
194+
* searching data.
195+
* @return this builder
196+
*/
197+
public Builder withIndexName(String newIndexName) {
198+
199+
Assert.hasText(newIndexName, "Index name may not be null or blank");
200+
201+
this.indexName = newIndexName;
202+
return this;
203+
}
204+
185205
/**
186206
* {@return the immutable configuration}
187207
*/
@@ -198,7 +218,7 @@ public Neo4jVectorStoreConfig build() {
198218

199219
public static final String DEFAULT_LABEL = "Document";
200220

201-
private static final String INDEX_NAME = "spring-ai-document-index";
221+
public static final String DEFAULT_INDEX_NAME = "spring-ai-document-index";
202222

203223
public static final String DEFAULT_EMBEDDING_PROPERTY = "embedding";
204224

@@ -275,7 +295,7 @@ public List<Document> similaritySearch(SearchRequest request) {
275295
WHERE score >= $threshold
276296
RETURN node, score
277297
""",
278-
Map.of("indexName", INDEX_NAME, "numberOfNearestNeighbours", request.getTopK(),
298+
Map.of("indexName", this.config.indexName, "numberOfNearestNeighbours", request.getTopK(),
279299
"embeddingValue", embedding, "threshold", request.getSimilarityThreshold()))
280300
.list(Neo4jVectorStore::recordToDocument);
281301
}
@@ -292,15 +312,16 @@ public void afterPropertiesSet() {
292312
.consume();
293313

294314
var vectorIndexExists = session
295-
.run("SHOW INDEXES YIELD name WHERE name = $name RETURN count(*) > 0", Map.of("name", INDEX_NAME))
315+
.run("SHOW INDEXES YIELD name WHERE name = $name RETURN count(*) > 0",
316+
Map.of("name", this.config.indexName))
296317
.single()
297318
.get(0)
298319
.asBoolean();
299320

300321
if (!vectorIndexExists) {
301322
var statement = "CALL db.index.vector.createNodeIndex($indexName, $label, $embeddingProperty, $embeddingDimension, $distanceType)";
302323
session.run(statement,
303-
Map.of("indexName", INDEX_NAME, "label", this.config.label, "embeddingProperty",
324+
Map.of("indexName", this.config.indexName, "label", this.config.label, "embeddingProperty",
304325
this.config.embeddingProperty, "embeddingDimension", this.config.embeddingDimension,
305326
"distanceType", this.config.distanceType.name))
306327
.consume();
@@ -323,7 +344,7 @@ private Map<String, Object> documentToRecord(Document document) {
323344
document.getMetadata().forEach((k, v) -> properties.put("metadata." + k, Values.value(v)));
324345
row.put("properties", properties);
325346

326-
row.put(DEFAULT_EMBEDDING_PROPERTY, Values.value(toFloatArray(embedding)));
347+
row.put(this.config.embeddingProperty, Values.value(toFloatArray(embedding)));
327348
return row;
328349
}
329350

0 commit comments

Comments
 (0)