From 90b20ff990ebe6ee6558f6903e6fbd1f606c3d62 Mon Sep 17 00:00:00 2001 From: Laura Trotta <153528055+l-trotta@users.noreply.github.com> Date: Wed, 24 Apr 2024 15:48:22 +0200 Subject: [PATCH] Full code for esql article (#787) * full code for esql article * build dependent on main project * code style fixes --- examples/esql-article/build.gradle.kts | 34 ++++ .../co/elastic/clients/esql/article/Book.java | 29 ++++ .../clients/esql/article/EsqlArticle.java | 164 ++++++++++++++++++ .../src/main/resources/application.conf | 3 + settings.gradle.kts | 9 +- 5 files changed, 238 insertions(+), 1 deletion(-) create mode 100644 examples/esql-article/build.gradle.kts create mode 100644 examples/esql-article/src/main/java/co/elastic/clients/esql/article/Book.java create mode 100644 examples/esql-article/src/main/java/co/elastic/clients/esql/article/EsqlArticle.java create mode 100644 examples/esql-article/src/main/resources/application.conf diff --git a/examples/esql-article/build.gradle.kts b/examples/esql-article/build.gradle.kts new file mode 100644 index 000000000..0a0ac8461 --- /dev/null +++ b/examples/esql-article/build.gradle.kts @@ -0,0 +1,34 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you 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 + * + * http://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. + */ +plugins { + id("java") +} + +java { + targetCompatibility = JavaVersion.VERSION_17 +} + +repositories { + mavenCentral() +} + +dependencies { + implementation(project(":java-client")) + implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-csv:2.17.0") +} diff --git a/examples/esql-article/src/main/java/co/elastic/clients/esql/article/Book.java b/examples/esql-article/src/main/java/co/elastic/clients/esql/article/Book.java new file mode 100644 index 000000000..88bd5ad1e --- /dev/null +++ b/examples/esql-article/src/main/java/co/elastic/clients/esql/article/Book.java @@ -0,0 +1,29 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you 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 + * + * http://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 co.elastic.clients.esql.article; + +public record Book( + String title, + String description, + String author, + Integer year, + String publisher, + Float ratings +) { +} diff --git a/examples/esql-article/src/main/java/co/elastic/clients/esql/article/EsqlArticle.java b/examples/esql-article/src/main/java/co/elastic/clients/esql/article/EsqlArticle.java new file mode 100644 index 000000000..7a8c490a0 --- /dev/null +++ b/examples/esql-article/src/main/java/co/elastic/clients/esql/article/EsqlArticle.java @@ -0,0 +1,164 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you 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 + * + * http://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 co.elastic.clients.esql.article; + +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch._helpers.bulk.BulkIngester; +import co.elastic.clients.elasticsearch._helpers.esql.jdbc.ResultSetEsqlAdapter; +import co.elastic.clients.elasticsearch._helpers.esql.objects.ObjectsEsqlAdapter; +import co.elastic.clients.elasticsearch.core.bulk.BulkOperation; +import co.elastic.clients.json.jackson.JacksonJsonpMapper; +import co.elastic.clients.transport.ElasticsearchTransport; +import co.elastic.clients.transport.rest_client.RestClientTransport; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.MappingIterator; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.exc.InvalidFormatException; +import com.fasterxml.jackson.databind.json.JsonMapper; +import com.fasterxml.jackson.dataformat.csv.CsvMapper; +import com.fasterxml.jackson.dataformat.csv.CsvSchema; +import org.apache.http.Header; +import org.apache.http.HttpHost; +import org.apache.http.message.BasicHeader; +import org.elasticsearch.client.RestClient; + +import java.io.FileInputStream; +import java.io.FileReader; +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.time.Duration; +import java.time.Instant; +import java.util.List; +import java.util.Properties; +import java.util.stream.Collectors; + +public class EsqlArticle { + + public static void main(String[] args) throws IOException, SQLException { + String dir = System.getProperty("user.dir"); + Properties prop = new Properties(); + Path path = Paths.get(dir, "examples", "esql-article", "src", "main", "resources", "application" + + ".conf"); + prop.load(new FileInputStream(path.toString())); + + String serverUrl = prop.getProperty("server-url"); + String apiKey = prop.getProperty("api-key"); + String csvPath = prop.getProperty("csv-file"); + + RestClient restClient = RestClient + .builder(HttpHost.create(serverUrl)) + .setDefaultHeaders(new Header[]{ + new BasicHeader("Authorization", "ApiKey " + apiKey) + }) + .build(); + + ObjectMapper mapper = JsonMapper.builder() + .build(); + + JacksonJsonpMapper jsonpMapper = new JacksonJsonpMapper(mapper); + + ElasticsearchTransport transport = new RestClientTransport( + restClient, jsonpMapper); + + ElasticsearchClient client = new ElasticsearchClient(transport); + + if (!client.indices().exists(ex -> ex.index("books")).value()) { + client.indices() + .create(c -> c + .index("books") + .mappings(mp -> mp + .properties("title", p -> p.text(t -> t)) + .properties("description", p -> p.text(t -> t)) + .properties("author", p -> p.text(t -> t)) + .properties("year", p -> p.short_(s -> s)) + .properties("publisher", p -> p.text(t -> t)) + .properties("ratings", p -> p.halfFloat(hf -> hf)) + )); + } + + Instant start = Instant.now(); + System.out.println("Starting BulkIndexer... \n"); + + CsvMapper csvMapper = new CsvMapper(); + CsvSchema schema = CsvSchema.builder() + .addColumn("title") // same order as in the csv + .addColumn("description") + .addColumn("author") + .addColumn("year") + .addColumn("publisher") + .addColumn("ratings") + .setColumnSeparator(';') + .setSkipFirstDataRow(true) + .build(); + + MappingIterator it = csvMapper + .readerFor(Book.class) + .with(schema) + .readValues(new FileReader(csvPath)); + + BulkIngester ingester = BulkIngester.of(bi -> bi + .client(client) + .maxConcurrentRequests(20) + .maxOperations(5000)); + + boolean hasNext = true; + + while (hasNext) { + try { + Book book = it.nextValue(); + ingester.add(BulkOperation.of(b -> b + .index(i -> i + .index("books") + .document(book)))); + hasNext = it.hasNextValue(); + } catch (JsonParseException | InvalidFormatException e) { + // ignore malformed data + } + } + + ingester.close(); + + client.indices().refresh(); + + Instant end = Instant.now(); + + System.out.println("Finished in: " + Duration.between(start, end).toMillis() + "\n"); + + String query = + """ + from books + | where author == "Isaac Asimov" + | sort year desc + | limit 10 + """; + List queryRes = (List) client.esql().query(ObjectsEsqlAdapter.of(Book.class), query); + + System.out.println("~~~\nObject result:\n" + queryRes.stream().map(Book::title).collect(Collectors.joining("\n"))); + + ResultSet resultSet = client.esql().query(ResultSetEsqlAdapter.INSTANCE, query); + + System.out.println("~~~\nResultSet result:"); + while (resultSet.next()) { + System.out.println(resultSet.getString("title")); + } + } +} diff --git a/examples/esql-article/src/main/resources/application.conf b/examples/esql-article/src/main/resources/application.conf new file mode 100644 index 000000000..fa70bd046 --- /dev/null +++ b/examples/esql-article/src/main/resources/application.conf @@ -0,0 +1,3 @@ +server-url=elasticsearch-server-url +api-key=elasticsearch-api-key +csv-file=/path/to/your/csv/books.csv diff --git a/settings.gradle.kts b/settings.gradle.kts index 11b843f2d..1f0d5a7e7 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,3 +1,5 @@ +import java.nio.file.Paths + /* * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with @@ -20,7 +22,8 @@ rootProject.name = "elasticsearch-java" // Include as subprojects all subdirectories that have a "build.gradle.kts" and no ".gradle-standalone" -(rootProject.projectDir.listFiles() ?: arrayOf()). +fun listFiles(dir: File){ + (dir.listFiles() ?: arrayOf()). filter { File(it, "build.gradle.kts").exists() }. filter { !File(it, ".gradle-standalone").exists() }. filter { it.name != "buildSrc" }. @@ -29,3 +32,7 @@ rootProject.name = "elasticsearch-java" include(dir.name) project(":" + dir.name).projectDir = dir } +} + +listFiles(rootProject.projectDir) +listFiles(Paths.get(rootProject.projectDir.path,"examples").toFile())