diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/docker-compose.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/docker-compose.adoc
index 2ed52679277..8085e26b757 100644
--- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/docker-compose.adoc
+++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/docker-compose.adoc
@@ -35,6 +35,9 @@ The following service connection factories are provided in the `spring-ai-spring
| Containers named `localstack/localstack`
| `ChromaConnectionDetails`
+| Containers named `docker.elastic.co/elasticsearch/elasticsearch`
+
+| `ElasticsearchConnectionDetails`
| Containers named `chromadb/chroma`, `ghcr.io/chroma-core/chroma`
| `MongoConnectionDetails`
diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/testcontainers.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/testcontainers.adoc
index 2f8b59d4182..1e7813cedeb 100644
--- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/testcontainers.adoc
+++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/testcontainers.adoc
@@ -38,6 +38,9 @@ The following service connection factories are provided in the `spring-ai-spring
| `ChromaConnectionDetails`
| Containers of type `ChromaDBContainer`
+| `ElasticsearchConnectionDetails`
+| Containers of type `ElasticsearchContainer`
+
| `MilvusServiceClientConnectionDetails`
| Containers of type `MilvusContainer`
diff --git a/spring-ai-spring-boot-docker-compose/pom.xml b/spring-ai-spring-boot-docker-compose/pom.xml
index 7f77cb1cbcd..864f2f63fac 100644
--- a/spring-ai-spring-boot-docker-compose/pom.xml
+++ b/spring-ai-spring-boot-docker-compose/pom.xml
@@ -55,6 +55,11 @@
${project.parent.version}
true
+
+ org.springframework.ai
+ spring-ai-autoconfigure-vector-store-elasticsearch
+ ${project.parent.version}
+
org.springframework.ai
spring-ai-autoconfigure-vector-store-weaviate
@@ -138,6 +143,14 @@
true
+
+
+ org.springframework.ai
+ spring-ai-elasticsearch-store
+ ${project.parent.version}
+ true
+
+
org.springframework.ai
diff --git a/spring-ai-spring-boot-docker-compose/src/main/java/org/springframework/ai/docker/compose/service/connection/elasticsearch/ElasticsearchDockerComposeConnectionDetailsFactory.java b/spring-ai-spring-boot-docker-compose/src/main/java/org/springframework/ai/docker/compose/service/connection/elasticsearch/ElasticsearchDockerComposeConnectionDetailsFactory.java
new file mode 100644
index 00000000000..23aa0b1e95d
--- /dev/null
+++ b/spring-ai-spring-boot-docker-compose/src/main/java/org/springframework/ai/docker/compose/service/connection/elasticsearch/ElasticsearchDockerComposeConnectionDetailsFactory.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2023-2024 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.ai.docker.compose.service.connection.elasticsearch;
+
+import org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchConnectionDetails;
+import org.springframework.boot.docker.compose.core.RunningService;
+import org.springframework.boot.docker.compose.service.connection.DockerComposeConnectionDetailsFactory;
+import org.springframework.boot.docker.compose.service.connection.DockerComposeConnectionSource;
+
+import java.util.List;
+
+/**
+ * A {@link DockerComposeConnectionDetailsFactory} implementation that creates
+ * {@link ElasticsearchConnectionDetails} for an Elasticsearch instance running in a
+ * Docker container.
+ *
+ * @author Laura Trotta
+ * @see DockerComposeConnectionDetailsFactory
+ * @see ElasticsearchConnectionDetails
+ * @see DockerComposeConnectionSource
+ * @since 1.0.2
+ */
+class ElasticsearchDockerComposeConnectionDetailsFactory
+ extends DockerComposeConnectionDetailsFactory {
+
+ private static final int ELASTICSEARCH_PORT = 9200;
+
+ protected ElasticsearchDockerComposeConnectionDetailsFactory() {
+ super("docker.elastic.co/elasticsearch/elasticsearch");
+ }
+
+ @Override
+ protected ElasticsearchConnectionDetails getDockerComposeConnectionDetails(DockerComposeConnectionSource source) {
+ return new ElasticsearchDockerComposeConnectionDetails(source.getRunningService());
+ }
+
+ /**
+ * {@link ElasticsearchConnectionDetails} backed by an {@code Elasticsearch}
+ * {@link RunningService}.
+ */
+ static class ElasticsearchDockerComposeConnectionDetails extends DockerComposeConnectionDetails
+ implements ElasticsearchConnectionDetails {
+
+ private final ElasticsearchEnvironment environment;
+
+ private final String host;
+
+ ElasticsearchDockerComposeConnectionDetails(RunningService service) {
+ super(service);
+ this.environment = new ElasticsearchEnvironment(service.env());
+ this.host = service.host();
+ }
+
+ @Override
+ public List getNodes() {
+ return List.of(new Node(host, ELASTICSEARCH_PORT, Node.Protocol.HTTPS, getUsername(), getPassword()));
+ }
+
+ @Override
+ public String getUsername() {
+ return "elastic";
+ }
+
+ @Override
+ public String getPassword() {
+ return environment.getPassword();
+ }
+
+ @Override
+ public String getPathPrefix() {
+ return "";
+ }
+
+ }
+
+}
diff --git a/spring-ai-spring-boot-docker-compose/src/main/java/org/springframework/ai/docker/compose/service/connection/elasticsearch/ElasticsearchEnvironment.java b/spring-ai-spring-boot-docker-compose/src/main/java/org/springframework/ai/docker/compose/service/connection/elasticsearch/ElasticsearchEnvironment.java
new file mode 100644
index 00000000000..35a449a8acf
--- /dev/null
+++ b/spring-ai-spring-boot-docker-compose/src/main/java/org/springframework/ai/docker/compose/service/connection/elasticsearch/ElasticsearchEnvironment.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2023-2024 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.ai.docker.compose.service.connection.elasticsearch;
+
+import java.util.Map;
+
+class ElasticsearchEnvironment {
+
+ private final String password;
+
+ ElasticsearchEnvironment(Map env) {
+ this.password = env.get("ELASTIC_PASSWORD");
+ }
+
+ String getPassword() {
+ return this.password;
+ }
+
+}
diff --git a/spring-ai-spring-boot-docker-compose/src/main/resources/META-INF/spring.factories b/spring-ai-spring-boot-docker-compose/src/main/resources/META-INF/spring.factories
index d6949d5de09..83a71aae869 100644
--- a/spring-ai-spring-boot-docker-compose/src/main/resources/META-INF/spring.factories
+++ b/spring-ai-spring-boot-docker-compose/src/main/resources/META-INF/spring.factories
@@ -16,6 +16,7 @@
org.springframework.boot.autoconfigure.service.connection.ConnectionDetailsFactory=\
org.springframework.ai.docker.compose.service.connection.chroma.ChromaDockerComposeConnectionDetailsFactory,\
+org.springframework.ai.docker.compose.service.connection.elasticsearch.ElasticsearchDockerComposeConnectionDetailsFactory,\
org.springframework.ai.docker.compose.service.connection.mongo.MongoDbAtlasLocalDockerComposeConnectionDetailsFactory,\
org.springframework.ai.docker.compose.service.connection.ollama.OllamaDockerComposeConnectionDetailsFactory,\
org.springframework.ai.docker.compose.service.connection.opensearch.AwsOpenSearchDockerComposeConnectionDetailsFactory,\
diff --git a/spring-ai-spring-boot-docker-compose/src/test/java/org/springframework/ai/docker/compose/service/connection/elasticsearch/ElasticsearchDockerComposeConnectionDetailsFactoryIT.java b/spring-ai-spring-boot-docker-compose/src/test/java/org/springframework/ai/docker/compose/service/connection/elasticsearch/ElasticsearchDockerComposeConnectionDetailsFactoryIT.java
new file mode 100644
index 00000000000..4816ed460aa
--- /dev/null
+++ b/spring-ai-spring-boot-docker-compose/src/test/java/org/springframework/ai/docker/compose/service/connection/elasticsearch/ElasticsearchDockerComposeConnectionDetailsFactoryIT.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2023-2024 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.ai.docker.compose.service.connection.elasticsearch;
+
+import org.json.JSONArray;
+import org.json.JSONObject;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchConnectionDetails;
+import org.springframework.boot.docker.compose.service.connection.test.AbstractDockerComposeIT;
+import org.springframework.util.StreamUtils;
+import org.testcontainers.utility.DockerImageName;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.net.URLConnection;
+import java.nio.charset.Charset;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class ElasticsearchDockerComposeConnectionDetailsFactoryIT extends AbstractDockerComposeIT {
+
+ protected ElasticsearchDockerComposeConnectionDetailsFactoryIT() {
+ super("elasticsearch-compose.yaml", DockerImageName.parse(getLatestElasticsearch()));
+ }
+
+ private static String getLatestElasticsearch() {
+ String imageName = "docker.elastic.co/elasticsearch/elasticsearch:";
+ try {
+ URL url = new URL("https://artifacts.elastic.co/releases/stack.json");
+ URLConnection connection = url.openConnection();
+ try (InputStream is = connection.getInputStream()) {
+ String result = StreamUtils.copyToString(is, Charset.defaultCharset());
+ JSONObject json = new JSONObject(result);
+ JSONArray releases = json.getJSONArray("releases");
+ JSONObject latest = (JSONObject) releases.get(releases.length() - 1);
+ return imageName + latest.getString("version");
+ }
+ }
+ catch (IOException e) {
+ throw new RuntimeException(
+ "Failed to retrieve latest Elasticsearch version from https://artifacts.elastic.co/releases/stack.json",
+ e);
+ }
+ }
+
+ @Test
+ void runCreatesConnectionDetails() {
+ ElasticsearchConnectionDetails connectionDetails = run(ElasticsearchConnectionDetails.class);
+ assertThat(connectionDetails.getNodes()).isNotEmpty();
+ }
+
+}
diff --git a/spring-ai-spring-boot-docker-compose/src/test/java/org/springframework/ai/docker/compose/service/connection/elasticsearch/ElasticsearchEnvironmentTests.java b/spring-ai-spring-boot-docker-compose/src/test/java/org/springframework/ai/docker/compose/service/connection/elasticsearch/ElasticsearchEnvironmentTests.java
new file mode 100644
index 00000000000..71501223127
--- /dev/null
+++ b/spring-ai-spring-boot-docker-compose/src/test/java/org/springframework/ai/docker/compose/service/connection/elasticsearch/ElasticsearchEnvironmentTests.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2023-2024 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.ai.docker.compose.service.connection.elasticsearch;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.Collections;
+import java.util.Map;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class ElasticsearchEnvironmentTests {
+
+ @Test
+ void getPasswordWhenNoPassword() {
+ ElasticsearchEnvironment environment = new ElasticsearchEnvironment(Collections.emptyMap());
+ assertThat(environment.getPassword()).isNull();
+ }
+
+ @Test
+ void getPasswordWhenHasPassword() {
+ ElasticsearchEnvironment environment = new ElasticsearchEnvironment(Map.of("ELASTIC_PASSWORD", "Ym9vcCE="));
+ assertThat(environment.getPassword()).isEqualTo("Ym9vcCE=");
+ }
+
+}
diff --git a/spring-ai-spring-boot-docker-compose/src/test/resources/org/springframework/ai/docker/compose/service/connection/elasticsearch/elasticsearch-compose.yaml b/spring-ai-spring-boot-docker-compose/src/test/resources/org/springframework/ai/docker/compose/service/connection/elasticsearch/elasticsearch-compose.yaml
new file mode 100644
index 00000000000..7cd4447e925
--- /dev/null
+++ b/spring-ai-spring-boot-docker-compose/src/test/resources/org/springframework/ai/docker/compose/service/connection/elasticsearch/elasticsearch-compose.yaml
@@ -0,0 +1,9 @@
+services:
+ elasticsearch:
+ image: '{imageName}'
+ ports:
+ - '9200'
+ environment:
+ - ELASTIC_PASSWORD=Ym9vcCE=
+ - discovery.type=single-node
+ - ES_JAVA_OPTS=-Xms128m -Xmx512m
diff --git a/spring-ai-spring-boot-testcontainers/pom.xml b/spring-ai-spring-boot-testcontainers/pom.xml
index 86b1c66477a..7e9d6f7bb09 100644
--- a/spring-ai-spring-boot-testcontainers/pom.xml
+++ b/spring-ai-spring-boot-testcontainers/pom.xml
@@ -62,6 +62,12 @@
${project.parent.version}
true
+
+ org.springframework.ai
+ spring-ai-autoconfigure-vector-store-elasticsearch
+ ${project.parent.version}
+ true
+
org.springframework.ai
spring-ai-autoconfigure-vector-store-mongodb-atlas
@@ -151,6 +157,14 @@
true
+
+
+ org.springframework.ai
+ spring-ai-elasticsearch-store
+ ${project.parent.version}
+ true
+
+
org.springframework.ai
@@ -308,6 +322,13 @@
true
+
+ org.testcontainers
+ elasticsearch
+ 1.21.3
+ true
+
+
org.testcontainers
localstack
diff --git a/spring-ai-spring-boot-testcontainers/src/main/java/org/springframework/ai/testcontainers/service/connection/elasticsearch/ElasticsearchContainerConnectionDetailsFactory.java b/spring-ai-spring-boot-testcontainers/src/main/java/org/springframework/ai/testcontainers/service/connection/elasticsearch/ElasticsearchContainerConnectionDetailsFactory.java
new file mode 100644
index 00000000000..b7b7eddc412
--- /dev/null
+++ b/spring-ai-spring-boot-testcontainers/src/main/java/org/springframework/ai/testcontainers/service/connection/elasticsearch/ElasticsearchContainerConnectionDetailsFactory.java
@@ -0,0 +1,69 @@
+package org.springframework.ai.testcontainers.service.connection.elasticsearch;
+
+import org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchConnectionDetails;
+import org.springframework.boot.ssl.SslBundle;
+import org.springframework.boot.testcontainers.service.connection.ContainerConnectionDetailsFactory;
+import org.springframework.boot.testcontainers.service.connection.ContainerConnectionSource;
+import org.testcontainers.elasticsearch.ElasticsearchContainer;
+
+import java.util.List;
+
+/**
+ * A {@link ContainerConnectionDetailsFactory} implementation that provides
+ * {@link ElasticsearchConnectionDetails} for a {@link ElasticsearchContainer}.
+ *
+ * @author Laura Trotta
+ * @see ContainerConnectionDetailsFactory
+ * @see ElasticsearchConnectionDetails
+ * @see ElasticsearchContainer
+ * @since 1.0.2
+ */
+class ElasticsearchContainerConnectionDetailsFactory
+ extends ContainerConnectionDetailsFactory {
+
+ @Override
+ public ElasticsearchConnectionDetails getContainerConnectionDetails(
+ ContainerConnectionSource source) {
+ return new ElasticsearchContainerConnectionDetails(source);
+ }
+
+ /**
+ * {@link ElasticsearchConnectionDetails} backed by a
+ * {@link ContainerConnectionSource}.
+ */
+ private static final class ElasticsearchContainerConnectionDetails
+ extends ContainerConnectionDetails implements ElasticsearchConnectionDetails {
+
+ private ElasticsearchContainerConnectionDetails(ContainerConnectionSource source) {
+ super(source);
+ }
+
+ @Override
+ public List getNodes() {
+ return List.of(new Node(getContainer().getHttpHostAddress(), getContainer().getMappedPort(9200),
+ Node.Protocol.HTTP, getUsername(), getPassword()));
+ }
+
+ @Override
+ public String getUsername() {
+ return "elastic";
+ }
+
+ @Override
+ public String getPassword() {
+ return "changeme";
+ }
+
+ @Override
+ public String getPathPrefix() {
+ return "";
+ }
+
+ @Override
+ public SslBundle getSslBundle() {
+ return super.getSslBundle();
+ }
+
+ }
+
+}
diff --git a/spring-ai-spring-boot-testcontainers/src/main/resources/META-INF/spring.factories b/spring-ai-spring-boot-testcontainers/src/main/resources/META-INF/spring.factories
index 19576a7a6f4..0b2720e3ff6 100644
--- a/spring-ai-spring-boot-testcontainers/src/main/resources/META-INF/spring.factories
+++ b/spring-ai-spring-boot-testcontainers/src/main/resources/META-INF/spring.factories
@@ -15,6 +15,7 @@
#
org.springframework.boot.autoconfigure.service.connection.ConnectionDetailsFactory=\
org.springframework.ai.testcontainers.service.connection.chroma.ChromaContainerConnectionDetailsFactory,\
+org.springframework.ai.testcontainers.service.connection.elasticsearch.ElasticsearchContainerConnectionDetailsFactory,\
org.springframework.ai.testcontainers.service.connection.milvus.MilvusContainerConnectionDetailsFactory,\
org.springframework.ai.testcontainers.service.connection.mongo.MongoDbAtlasLocalContainerConnectionDetailsFactory,\
org.springframework.ai.testcontainers.service.connection.ollama.OllamaContainerConnectionDetailsFactory,\
diff --git a/spring-ai-spring-boot-testcontainers/src/test/java/org/springframework/ai/testcontainers/service/connection/elasticsearch/ElasticsearchContainerConnectionDetailsFactoryIT.java b/spring-ai-spring-boot-testcontainers/src/test/java/org/springframework/ai/testcontainers/service/connection/elasticsearch/ElasticsearchContainerConnectionDetailsFactoryIT.java
new file mode 100644
index 00000000000..87577e8d766
--- /dev/null
+++ b/spring-ai-spring-boot-testcontainers/src/test/java/org/springframework/ai/testcontainers/service/connection/elasticsearch/ElasticsearchContainerConnectionDetailsFactoryIT.java
@@ -0,0 +1,121 @@
+package org.springframework.ai.testcontainers.service.connection.elasticsearch;
+
+import org.apache.http.HttpHost;
+import org.awaitility.Awaitility;
+import org.elasticsearch.client.RestClient;
+import org.junit.jupiter.api.Test;
+import org.springframework.ai.document.Document;
+import org.springframework.ai.embedding.EmbeddingModel;
+import org.springframework.ai.transformers.TransformersEmbeddingModel;
+import org.springframework.ai.vectorstore.SearchRequest;
+import org.springframework.ai.vectorstore.VectorStore;
+import org.springframework.ai.vectorstore.elasticsearch.ElasticsearchVectorStore;
+import org.springframework.ai.vectorstore.elasticsearch.ElasticsearchVectorStoreOptions;
+import org.springframework.boot.test.context.runner.ApplicationContextRunner;
+import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.io.DefaultResourceLoader;
+import org.testcontainers.elasticsearch.ElasticsearchContainer;
+import org.testcontainers.junit.jupiter.Container;
+import org.testcontainers.junit.jupiter.Testcontainers;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.time.Duration;
+import java.util.List;
+import java.util.Map;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.hamcrest.Matchers.hasSize;
+
+@Testcontainers
+class ElasticsearchContainerConnectionDetailsFactoryIT {
+
+ @Container
+ @ServiceConnection
+ private static final ElasticsearchContainer elasticsearch = new ElasticsearchContainer(
+ ElasticsearchImage.DEFAULT_IMAGE)
+ .withStartupTimeout(Duration.ofSeconds(30))
+ .withEnv("ES_JAVA_OPTS", "-Xms256m -Xmx256m")
+ .withEnv("xpack.security.enabled", "false");
+
+ private final List documents = List.of(
+ new Document("1", getText("classpath:/test/data/spring.ai.txt"), Map.of("meta1", "meta1")),
+ new Document("2", getText("classpath:/test/data/time.shelter.txt"), Map.of()),
+ new Document("3", getText("classpath:/test/data/great.depression.txt"), Map.of("meta2", "meta2")));
+
+ @Test
+ public void addAndSearchTest() {
+ getContextRunner().run(context -> {
+ VectorStore vectorStore = context.getBean(VectorStore.class);
+ vectorStore.add(this.documents);
+
+ Awaitility.await()
+ .until(() -> vectorStore.similaritySearch(
+ SearchRequest.builder().query("Great Depression").topK(1).similarityThreshold(0).build()),
+ hasSize(1));
+
+ List results = vectorStore.similaritySearch(
+ SearchRequest.builder().query("Great Depression").topK(1).similarityThreshold(0).build());
+
+ assertThat(results).hasSize(1);
+ Document resultDoc = results.get(0);
+ assertThat(resultDoc.getId()).isEqualTo(this.documents.get(2).getId());
+ assertThat(resultDoc.getText()).contains("The Great Depression (1929–1939) was an economic " + "shock");
+ assertThat(resultDoc.getMetadata()).hasSize(2);
+ assertThat(resultDoc.getMetadata()).containsKey("meta2");
+ assertThat(resultDoc.getMetadata()).containsKey("distance");
+
+ // Remove all documents from the store
+ vectorStore.delete(this.documents.stream().map(Document::getId).toList());
+
+ Awaitility.await()
+ .until(() -> vectorStore.similaritySearch(
+ SearchRequest.builder().query("Great Depression").topK(1).similarityThreshold(0).build()),
+ hasSize(0));
+
+ });
+ }
+
+ private ApplicationContextRunner getContextRunner() {
+ return new ApplicationContextRunner().withUserConfiguration(Config.class);
+ }
+
+ private String getText(String uri) {
+ var resource = new DefaultResourceLoader().getResource(uri);
+ try {
+ return resource.getContentAsString(StandardCharsets.UTF_8);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Configuration(proxyBeanMethods = false)
+ static class Config {
+
+ @Bean
+ public EmbeddingModel embeddingModel() {
+ return new TransformersEmbeddingModel();
+ }
+
+ @Bean
+ RestClient restClient() {
+ return RestClient.builder(new HttpHost(elasticsearch.getHost(), elasticsearch.getMappedPort(9200), "http"))
+ .build();
+ }
+
+ @Bean
+ public ElasticsearchVectorStore vectorStoreDefault(EmbeddingModel embeddingModel, RestClient restClient) {
+ ElasticsearchVectorStoreOptions options = new ElasticsearchVectorStoreOptions();
+ options.setDimensions(384);
+ return ElasticsearchVectorStore.builder(restClient, embeddingModel)
+ .initializeSchema(true)
+ .options(options)
+ .build();
+ }
+
+ }
+
+}
diff --git a/spring-ai-spring-boot-testcontainers/src/test/java/org/springframework/ai/testcontainers/service/connection/elasticsearch/ElasticsearchImage.java b/spring-ai-spring-boot-testcontainers/src/test/java/org/springframework/ai/testcontainers/service/connection/elasticsearch/ElasticsearchImage.java
new file mode 100644
index 00000000000..9eca6a75017
--- /dev/null
+++ b/spring-ai-spring-boot-testcontainers/src/test/java/org/springframework/ai/testcontainers/service/connection/elasticsearch/ElasticsearchImage.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2023-2024 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.ai.testcontainers.service.connection.elasticsearch;
+
+import org.testcontainers.utility.DockerImageName;
+
+/**
+ * @author Laura Trotta
+ */
+public final class ElasticsearchImage {
+
+ public static final DockerImageName DEFAULT_IMAGE = DockerImageName
+ .parse("docker.elastic.co/elasticsearch/elasticsearch:9.1.2");
+
+ private ElasticsearchImage() {
+
+ }
+
+}