GH-1316: Elasticsearch vector store - Wrong error reported fix

Fixes: https://github.com/spring-projects/spring-ai/issues/1316

* Handling missing index case
* Docs update
* User header for observability
* Same exception management for delete
This commit is contained in:
Laura Trotta
2024-09-09 17:58:29 +02:00
committed by GitHub
parent 5b6a60db9a
commit 4f62ac1cee
2 changed files with 15 additions and 12 deletions

View File

@@ -50,12 +50,14 @@ TIP: Refer to the xref:getting-started.adoc#repositories[Repositories] section t
The vector store implementation can initialize the requisite schema for you, but you must opt-in by specifying the `initializeSchema` boolean in the appropriate constructor or by setting `...initialize-schema=true` in the `application.properties` file.
Alternatively you can opt-out the initialization and create the index manually using the Elasticsearch client, which can be useful if the index needs advanced mapping or additional configuration.
NOTE: this is a breaking change! In earlier versions of Spring AI, this schema initialization happened by default.
Please have a look at the list of <<elasticsearchvector-properties,configuration parameters>> for the vector store to learn about the default values and configuration options.
These properties can be also set by configuring the `ElasticsearchVectorStoreOptions` bean.
Additionally, you will need a configured `EmbeddingModel` bean. Refer to the xref:api/embeddings.adoc#available-implementations[EmbeddingModel] section for more information.

View File

@@ -105,6 +105,7 @@ public class ElasticsearchVectorStore extends AbstractObservationVectorStore imp
Objects.requireNonNull(embeddingModel, "EmbeddingModel must not be null");
this.elasticsearchClient = new ElasticsearchClient(new RestClientTransport(restClient, new JacksonJsonpMapper(
new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false))));
elasticsearchClient.withTransportOptions(t -> t.addHeader("user-agent", "spring-ai"));
this.embeddingModel = embeddingModel;
this.options = options;
this.filterExpressionConverter = new ElasticsearchAiSearchFilterExpressionConverter();
@@ -112,6 +113,11 @@ public class ElasticsearchVectorStore extends AbstractObservationVectorStore imp
@Override
public void doAdd(List<Document> documents) {
// For the index to be present, either it must be pre-created or set the
// initializeSchema to true.
if (!indexExists()) {
throw new IllegalArgumentException("Index not found");
}
BulkRequest.Builder bulkRequestBuilder = new BulkRequest.Builder();
for (Document document : documents) {
@@ -119,13 +125,8 @@ public class ElasticsearchVectorStore extends AbstractObservationVectorStore imp
logger.debug("Calling EmbeddingModel for document id = " + document.getId());
document.setEmbedding(this.embeddingModel.embed(document));
}
// We call operations on BulkRequest.Builder only if the index exists.
// For the index to be present, either it must be pre-created or set the
// initializeSchema to true.
if (indexExists()) {
bulkRequestBuilder.operations(op -> op
.index(idx -> idx.index(this.options.getIndexName()).id(document.getId()).document(document)));
}
bulkRequestBuilder.operations(op -> op
.index(idx -> idx.index(this.options.getIndexName()).id(document.getId()).document(document)));
}
BulkResponse bulkRequest = bulkRequest(bulkRequestBuilder.build());
if (bulkRequest.errors()) {
@@ -141,13 +142,13 @@ public class ElasticsearchVectorStore extends AbstractObservationVectorStore imp
@Override
public Optional<Boolean> doDelete(List<String> idList) {
BulkRequest.Builder bulkRequestBuilder = new BulkRequest.Builder();
// We call operations on BulkRequest.Builder only if the index exists.
// For the index to be present, either it must be pre-created or set the
// initializeSchema to true.
if (indexExists()) {
for (String id : idList) {
bulkRequestBuilder.operations(op -> op.delete(idx -> idx.index(this.options.getIndexName()).id(id)));
}
if (!indexExists()) {
throw new IllegalArgumentException("Index not found");
}
for (String id : idList) {
bulkRequestBuilder.operations(op -> op.delete(idx -> idx.index(this.options.getIndexName()).id(id)));
}
return Optional.of(bulkRequest(bulkRequestBuilder.build()).errors());
}