Skip to content

Commit b428e2e

Browse files
Allowing a custom embedding field by using a record instead of a map
Signed-off-by: jonghoon park <[email protected]>
1 parent edc3566 commit b428e2e

File tree

4 files changed

+63
-16
lines changed

4 files changed

+63
-16
lines changed

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

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

19+
import org.springframework.ai.vectorstore.elasticsearch.common.ElasticsearchVectorStoreConstants;
1920
import org.springframework.ai.vectorstore.properties.CommonVectorStoreProperties;
2021
import org.springframework.ai.vectorstore.elasticsearch.SimilarityFunction;
2122
import org.springframework.boot.context.properties.ConfigurationProperties;
@@ -50,7 +51,7 @@ public class ElasticsearchVectorStoreProperties extends CommonVectorStorePropert
5051
/**
5152
* The name of the vector field to search against
5253
*/
53-
private String embeddingFieldName = "embedding";
54+
private String embeddingFieldName = ElasticsearchVectorStoreConstants.DEFAULT_EMBEDDING_FIELD_NAME;
5455

5556
public String getIndexName() {
5657
return this.indexName;

vector-stores/spring-ai-elasticsearch-store/src/main/java/org/springframework/ai/vectorstore/elasticsearch/ElasticsearchVectorStore.java

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
3333
import co.elastic.clients.transport.Version;
3434
import co.elastic.clients.transport.rest_client.RestClientTransport;
35+
import com.fasterxml.jackson.annotation.JsonAnyGetter;
36+
import com.fasterxml.jackson.annotation.JsonIgnore;
3537
import com.fasterxml.jackson.databind.DeserializationFeature;
3638
import com.fasterxml.jackson.databind.ObjectMapper;
3739
import org.elasticsearch.client.RestClient;
@@ -189,12 +191,12 @@ public void doAdd(List<Document> documents) {
189191
List<float[]> embeddings = this.embeddingModel.embed(documents, EmbeddingOptionsBuilder.builder().build(),
190192
this.batchingStrategy);
191193

192-
for (int i = 0; i < embeddings.size(); i++) {
193-
Document document = documents.get(i);
194-
float[] embedding = embeddings.get(i);
195-
bulkRequestBuilder.operations(op -> op.index(idx -> idx.index(this.options.getIndexName())
196-
.id(document.getId())
197-
.document(getDocument(document, embedding, this.options.getEmbeddingFieldName()))));
194+
for (Document document : documents) {
195+
ElasticSearchDocument doc = new ElasticSearchDocument(document.getId(), document.getText(),
196+
document.getMetadata(), embeddings.get(documents.indexOf(document)),
197+
this.options.getEmbeddingFieldName());
198+
bulkRequestBuilder.operations(
199+
op -> op.index(idx -> idx.index(this.options.getIndexName()).id(document.getId()).document(doc)));
198200
}
199201
BulkResponse bulkRequest = bulkRequest(bulkRequestBuilder.build());
200202
if (bulkRequest.errors()) {
@@ -207,13 +209,6 @@ public void doAdd(List<Document> documents) {
207209
}
208210
}
209211

210-
private Object getDocument(Document document, float[] embedding, String embeddingFieldName) {
211-
Assert.notNull(document.getText(), "document's text must not be null");
212-
213-
return Map.of("id", document.getId(), "content", document.getText(), "metadata", document.getMetadata(),
214-
embeddingFieldName, embedding);
215-
}
216-
217212
@Override
218213
public void doDelete(List<String> idList) {
219214
BulkRequest.Builder bulkRequestBuilder = new BulkRequest.Builder();
@@ -379,6 +374,25 @@ public static Builder builder(RestClient restClient, EmbeddingModel embeddingMod
379374
return new Builder(restClient, embeddingModel);
380375
}
381376

377+
/**
378+
* The representation of {@link Document} along with its embedding.
379+
*
380+
* @param id The id of the document
381+
* @param content The content of the document
382+
* @param metadata The metadata of the document
383+
* @param embedding The vectors representing the content of the document
384+
* @param embeddingFieldName The field name used in the serialized JSON for the
385+
* embedding vector
386+
*/
387+
public record ElasticSearchDocument(String id, String content, Map<String, Object> metadata,
388+
@JsonIgnore float[] embedding, @JsonIgnore String embeddingFieldName) {
389+
390+
@JsonAnyGetter
391+
public Map<String, Object> dynamicEmbeddingField() {
392+
return Map.of(embeddingFieldName, embedding);
393+
}
394+
}
395+
382396
public static class Builder extends AbstractVectorStoreBuilder<Builder> {
383397

384398
private final RestClient restClient;

vector-stores/spring-ai-elasticsearch-store/src/main/java/org/springframework/ai/vectorstore/elasticsearch/ElasticsearchVectorStoreOptions.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
package org.springframework.ai.vectorstore.elasticsearch;
1818

19+
import org.springframework.ai.vectorstore.elasticsearch.common.ElasticsearchVectorStoreConstants;
20+
1921
/**
2022
* Provided Elasticsearch vector option configuration.
2123
* https://www.elastic.co/guide/en/elasticsearch/reference/current/dense-vector.html
@@ -29,7 +31,7 @@ public class ElasticsearchVectorStoreOptions {
2931
/**
3032
* The name of the index to store the vectors.
3133
*/
32-
private String indexName = "spring-ai-document-index";
34+
private String indexName = ElasticsearchVectorStoreConstants.DEFAULT_INDEX_NAME;
3335

3436
/**
3537
* The number of dimensions in the vector.
@@ -44,7 +46,7 @@ public class ElasticsearchVectorStoreOptions {
4446
/**
4547
* The name of the vector field to search against
4648
*/
47-
private String embeddingFieldName = "embedding";
49+
private String embeddingFieldName = ElasticsearchVectorStoreConstants.DEFAULT_EMBEDDING_FIELD_NAME;
4850

4951
public String getIndexName() {
5052
return this.indexName;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Copyright 2023-2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.ai.vectorstore.elasticsearch.common;
18+
19+
/**
20+
* Common value constants for Elasticsearch VectorStore.
21+
*
22+
* @author Jonghoon Park
23+
*/
24+
public class ElasticsearchVectorStoreConstants {
25+
26+
public static final String DEFAULT_INDEX_NAME = "spring-ai-document-index";
27+
28+
public static final String DEFAULT_EMBEDDING_FIELD_NAME = "embedding";
29+
30+
}

0 commit comments

Comments
 (0)