I tried using Elasticsearch API in Java

Trigger

In implementing Elasticsearch API using Java The basic usage is also in Qiita and in the official reference, but I decided to write this article because there are few articles that are a little complicated or have more practical description or code.

Those who are the subject of this article

--Those who want to or plan to develop using Elasticsearch API in Java --Elasticsearch beginners

Environment (at the time of development)

--Elasticsearch API version: 7.3.2 --Java version: 8 --Spring Boot version: 1.5.15 --maven version: 2.17

Preparation

pom.xml


<dependency>
    <groupId>org.elasticsearch</groupId>
    <artifactId>elasticsearch</artifactId>
    <version>7.3.2</version>
</dependency>

<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-high-level-client</artifactId>
    <version>7.3.2</version>
</dependency>

With the above description, you can use the Elasticsearch library.

Basic library description and usage

* All the column names, field names, IDs, etc. that appear after that do not actually exist. </ font>

SearchRequest When translating the reference English

SearchRequest is used for operations that search for documents, aggregates, and suggestions, and also provides a way to request highlighting of the resulting document.

It says, but I think it's like a masterpiece for sending requests to Elasticsearch using the API.

java


SearchRequest searchRequest = new SearchRequest();

Reference: https://www.elastic.co/guide/en/elasticsearch/client/java-rest/master/java-rest-high-search.html

SearchSourceBuilder SearchSourceBuilder is for adding search parameters.

java


SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

Reference: https://www.elastic.co/guide/en/elasticsearch/client/java-rest/master/java-rest-high-search.html

RestHighLevelClient RestHighLevelClient is a REST client recommended to replace the previously used Transport Client. By using it, you can access Elasticsearch from your Java app via http.

java


final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY,
    new UsernamePasswordCredentials("user", "password")
);

RestHighLevelClient client = new RestHighLevelClient(
    RestClient.builder(new HttpHost("localhost", 9200, "https"))
        .setHttpClientConfigCallback(httpAsyncClientBuilder -> httpAsyncClientBuilder
          .setDefaultCredentialsProvider(credentialsProvider))
);

searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);

Reference: https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/_basic_authentication.html

function score query In the function score query, multiple conditions (functions) can be described in the functions section, and sorting is performed using the sum of the scores for each condition.

Just an example


FunctionScoreQueryBuilder functionScoreQueryBuilder = null;
ArrayList<FunctionScoreQueryBuilder.FilterFunctionBuilder> functionScoreArrayList = new ArrayList<>();
//You can add more than one
filterFunctionList.add(
    new FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.termQuery("FashionItemId", "1"),
        ScoreFunctionBuilders.fieldValueFactorFunction("custom_score.").factor(Float.valueOf("0.0254389"
)).missing(0.2)));
//ArrayList type to FunctionScoreQueryBuilder.FilterFunctionBuilder[]To
FunctionScoreQueryBuilder.FilterFunctionBuilder[] functions = functionScoreArrayList.toArray(new FunctionScoreQueryBuilder.FilterFunctionBuilder[functionScoreArrayList.size()]);
functionScoreQueryBuilder = new FunctionScoreQueryBuilder(queryBuilder, functions).scoreMode(FunctionScoreQuery.ScoreMode.SUM).boostMode(CombineFunction.REPLACE);
searchSourceBuilder.query(functionScoreQueryBuilder);
  • Function ScoreQuery Builder has few articles that are really helpful ...

Reference: https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-function-score-query.html

count It can be specified as .count for RestHighLevelClient.

java


CountResponse countResponse = null;
countResponse = restHighLevelClient.count(searchRequest, RequestOptions.DEFAULT);

Then, you can get the number of hits in searchRequest in the form of CountResponse.

Reference: https://www.elastic.co/guide/en/elasticsearch/reference/current/search-count.html

search It can be specified with .search for RestHighLevelClient.

java


SearchResponse searchResponse = null;
searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

Then, you can get the search results that hit searchRequest in the form of SearchResponse.

Reference: https://www.elastic.co/guide/en/elasticsearch/reference/current/search-search.html

_source Elasticsearch's _source is like a SELECT clause in SQL. In the case of API, specify the field to fetch using fetchSource. By narrowing down the fields to be acquired, the amount of data can be reduced, so speed improvement can be expected. Specify the field to be acquired in the first argument and the field to be excluded in the second argument. In the case of count mentioned above, it is okay without specifying.

java


searchSourceBuilder.fetchSource(new String[]{"FashionItemId", "ItemPrice", "FashionItemSize",
    "FashionItemLargeCategory", "FashionItemSmallCategory"},
    "ExclusionFashionItemId");

Reference: https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high-search.html#_source_filtering

Sort It is Order By in SQL. Use FieldSortBuilder to specify the sort.

When sorting by multiple columns


return searchSourceBuilder.sort(new FieldSortBuilder("ItemPrice").order(SortOrder.ASC))
    .sort(new FieldSortBuilder("FashionItemId").order(SortOrder.DESC))
    .sort(new FieldSortBuilder("StartDatetime").order(SortOrder.DESC));

Reference: https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high-search.html#_specifying_sorting

from & size It corresponds to offset & limit in SQL. You can specify it with .from`` .to for SearchSourceBuilder mentioned above.

java


SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.from(0);
searchSourceBuilder.size(100);

Reference: https://www.elastic.co/guide/en/elasticsearch/client/java-rest/master/java-rest-high-search.html#_using_the_searchsourcebuilder

BoolQuery Used to combine other queries. You can combine AND, OR, NOT. There are four types of BoolQuery.

Query Description
must It is AND in SQL. The score will be calculated according to the specified conditions.
filter It is AND in SQL. Unlike must, the score is not calculated.
should It is OR in SQL.
must not It is NOT in SQL.

Typical search query

termQuery Whether it matches. In SQL = (equal) Reference: https://www.elastic.co/guide/en/elasticsearch/reference/7.8/query-dsl-term-query.html

temrsQuery Is there a match? IN clause in SQL Reference: https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/java-term-level-queries.html#java-query-dsl-terms-query

rangeQuery Is there a specified range? > =, <=, <,> In SQL Reference: https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/java-term-level-queries.html#java-query-dsl-range-query

Example (SQL vs ElasticSearch vs Java)

For SQL


AND StartDatetime >= '2019-12-06 17:33:18'
AND (
    (
        FashionItemLargeCategory <> 1
        AND FashionItemSmallCategory NOT IN (10,20,30)
        AND FashionItemSize IN (1,2)
    ) OR (
        (
            FashionItemLargeCategory = 2
            OR FashionItemSmallCategory  IN (40,50,60)
        )
        AND FashionItemSize  IN (9,10)
    )
)

For Elasticsearch


"bool": {
  "filter": [
    {
      "range": {
        "StartDatetime": {
          "from": null,
          "to": "2019-12-06 17:33:18",
          "include_lower": true,
          "include_upper": false
        }
      }
    },
    {
      "bool": {
        "filter": [
          {
            "bool": {
              "should": [
                {
                  "bool": {
                    "filter": [
                      {
                        "terms": {
                          "FashionItemSize ": [
                            1,
                            2
                          ]
                        }
                      }
                    ],
                    "must_not": [
                      {
                        "term": {
                          "FashionItemLargeCategory ": {
                            "value": 1,
                            "boost": 1
                          }
                        }
                      },
                      {
                        "terms": {
                          "FashionItemSmallCategory ": [
                            10,
                            20,
                            30
                          ]
                        }
                      }
                    ]
                  }
                },
                {
                  "bool": {
                    "filter": [
                      {
                        "terms": {
                          "FashionItemSize": [
                            9,
                            10
                          ]
                        }
                      }
                    ],
                    "should": [
                        {
                          "term": {
                            "FashionItemLargeCategory ": {
                              "value": 1
                            }
                          }
                        },
                        {
                          "terms": {
                            "FashionItemSmallCategory  ": [
                              40,
                              50,
                              60
                            ]
                          }
                        }
                    ]
                  }
                }
              ]
            }
          }
        ]
      }
    }
  ]
}

(It's very complicated and hard to see ...)

For java


integer[] smallCategories1 = {10, 20, 30};
integer[] itemSize1 = {1, 2};
integer[] smallCategories2 = {40, 50, 60};
integer[] itemSize2 = {9, 10};

BoolQueryBuilder qb1 = boolQuery()
    .mustNot(termQuery("FashionItemLargeCategory", 1))
    .mustNot(termsQuery("FashionItemSmallCategory", smallCategories1))
    .filter(termsQuery("FashionItemSize" , itemSize1));

BoolQueryBuilder qb2 = boolQuery()
    .should(termQuery("FashionItemLargeCategory", 2))
    .should(termsQuery("FashionItemSmallCategory", smallCategories2))
    .filter(termsQuery("FashionItemSize", itemSize2));

BoolQueryBuilder qb3 = boolQuery()
    .should(qb1)
    .should(qb2);

BoolQueryBuilder qb4 = boolQuery()
    .filter(rangeQuery("StartDatetime").from(null).lt("2019-12-06 17:33:18"))
    .filter(qb3);

Method of verification

You can get Elasticsearch query by doing toString () to BoolQueryBuilder. Check if the query is correct by comparing the result with the expected query or hitting it with Kibana.

Example&nbsp;(SQL&nbsp;vs&nbsp;ElasticSearch&nbsp;vs&nbsp;Java)&nbsp;When validating BoolQueryBuilder queries


System.out.println(qb4.toString());

Finally

This article is just the information at the time when I first touched it. At that time, there were few articles, but nowadays, if you look it up, there may be many good articles. I hope it will be helpful for those who are new to the Elasticsearch API.

Recommended Posts

I tried using Elasticsearch API in Java
I tried using Java8 Stream API
I tried using JWT in Java
I tried using Google Cloud Vision API in Java
I tried using Java REPL
I tried metaprogramming in Java
I tried Mastodon's Toot and Streaming API in Java
I tried using an extended for statement in Java
I tried using Java memo LocalDate
I tried using GoogleHttpClient of Java
Elasticsearch Operation via REST API using Apache HttpClient in Java
I tried using Dapr in Java to facilitate microservice development
Try using the Stream API in Java
I tried the new era in Java
Try using JSON format API in Java
I tried using OpenCV with Java + Tomcat
I tried using Gson
I tried using TestNG
I tried using Galasa
Zabbix API in Java
[For beginners] I tried using DBUnit in Eclipse
ChatWork4j for using the ChatWork API in Java
[For beginners] I tried using JUnit 5 in Eclipse
[Java] API creation using Jerjey (Jax-rs) in eclipse
I tried to implement deep learning in Java
Try using GCP's Cloud Vision API in Java
[API] I tried using the zip code search API
I tried to output multiplication table in Java
I tried to create Alexa skill in Java
Try using the COTOHA API parsing in Java
I tried to make a talk application in Java using AI "A3RT"
I tried using a database connection in Android development
Try using RocksDB in Java
I tried to implement Firebase push notification in Java
I tried to operate SQS using AWS Java SDK
I made roulette in Java.
# 2 [Note] I tried to calculate multiplication tables in Java.
I tried using azure cloud-init
Java Stream API in 5 minutes
I tried to create a Clova skill in Java
I tried Drools (Java, InputStream)
I tried to make a login function in Java
I tried using Log4j2 on a Java EE server
I tried using Apache Wicket
[Java] I tried to implement Yahoo API product search
I tried passing Java Silver in 2 weeks without knowing Java
I tried to implement the Euclidean algorithm in Java
~ I tried to learn functional programming in Java now ~
I tried scraping a stock chart using Java (Jsoup)
I tried to find out what changed in Java 9
I tried text extraction (OCR) in Ruby using Vision API (Trained Machine Learning Model)
Object-oriented child !? I tried Deep Learning in Java (trial edition)
I tried to introduce UI animation to Pokedex using Poké API
I tried to convert a string to a LocalDate type in Java
Translate using Microsoft Translator Text API in Java (Japanese → English)
Tips for using Salesforce SOAP and Bulk API in Java
I tried to make a client of RESAS-API in Java
I was addicted to using Java's Stream API in Scala
I tried using the CameraX library with Android Java Fragment
I tried using anakia + Jing now
I sent an email in Java