Conseils pour le client REST de haut niveau Java

Ceci est l'article du 11ème jour du Calendrier de l'Avent Elastic Stack (Elasticsearch) 2019

introduction

Elasticsearch est accessible via http à partir des applications Java en utilisant "Java High Level REST Client"

Auparavant, "TransportClient" était utilisé, mais il a été abandonné dans la version 8.0. Pour, "Conseils pour le client REST de haut niveau Java" ou "REST de bas niveau Java Client "est recommandé.

Cette fois, je présenterai un exemple d'utilisation axé sur la recherche (API de recherche).

point important

Exemple) Elasticsearch(7.0) Java High Level REST(7.0) → OK Elasticsearch(7.0) Java High Level REST(6.8) → NG

Préparation

Environnement Elasticsearch → Elastic Cloud Java8(JDK1.8.0)

Créer l'index "qiita"

PUT /qiita
{
  "mappings": {
    "properties": {
      "user":    { "type": "keyword" },  
      "post_date":  { "type": "date"  }, 
      "active":  { "type": "boolean"  },
      "message":   { "type": "text"  }     
    }
  }
}

POST qiita/_doc
{
    "user" : "qiita",
    "post_date" : "2019-12-11T00:10:30Z",
    "active":"false",
    "message" : "trying out High Level REST Client"
}

GET qiita/_search
...
      {
        "_index" : "qiita",
        "_type" : "_doc",
        "_id" : "yjDo5m4Bj4TzcUq3pmoX",
        "_score" : 1.0,
        "_source" : {
          "user" : "qiita",
          "post_date" : "2019-12-11T00:10:30Z",
          "active" : "false",
          "message" : "trying out High Level REST Client"
        }
      }
...

pon.xml

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

Créer Clinent pour la connexion

Fondamentalement, dans l'exemple de Initialization aucun problème

RestHighLevelClient client = new RestHighLevelClient(
        RestClient.builder(
                new HttpHost("localhost", 9200, "http"),
                new HttpHost("localhost", 9201, "http")));

client.close();

Pour Elastic Cloud

Si vous avez introduit une fonction d'authentification telle qu'Elastic Cloud, vous devez définir les paramètres suivants.

String username = "elastic";
String password = "pass";
String host = "host";
int port = 9243;
int nextPort = 9244;
String protocol = "https";


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

RestClientBuilder client = RestClient.builder(
                new HttpHost(host, port, protocol),
                new HttpHost(host, nextPort, protocol))
                .setHttpClientConfigCallback((h) -> h.setDefaultCredentialsProvider(credentialsProvider));

RestHighLevelClient client = new RestHighLevelClient(client);

client.close();

L'acquisition des données

Vous pouvez obtenir quelque chose de similaire à "GET qiita / _search" en utilisant le client que vous avez créé précédemment.

try (RestHighLevelClient client = new RestHighLevelClient(client)) {

            SearchSourceBuilder searchBuilder = SearchSourceBuilder.searchSource();
            // quite*Vous pouvez spécifier un caractère générique comme
            SearchRequest request = new SearchRequest("qiita").source(searchBuilder);
            //L'acquisition des données
            SearchHits hits = client.search(request, RequestOptions.DEFAULT).getHits();
            for(SearchHit hit : hits) {
                Map<String, Object> sourceAsMap = hit.getSourceAsMap();

          //Définissez la valeur de chaque enregistrement
                String user = (String) sourceAsMap.get("user");
                String post_date = (String) sourceAsMap.get("post_date");
                String message = (String) sourceAsMap.get("message");
    
                System.out.println(String.format("user:%s data:%s message:%s",user , post_date, message));
            }
}catch (IOException io) {}

Référence: API de recherche

Réglage de la taille

Définir sur "Search Source Builder" La taille par défaut n'est que de 10

// default 10
SearchSourceBuilder searchBuilder = SearchSourceBuilder.searchSource();
searchBuilder.size(100);
            

Trier

Définir sur "Search Source Builder" Basculer entre ASC et DESC avec l'ordre de tri

SearchSourceBuilder searchBuilder = SearchSourceBuilder.searchSource();
searchBuilder.sort(new FieldSortBuilder("_id").order(SortOrder.DESC));

Requête de recherche (filtre)

Créer des requêtes est tout au sujet Voici quelques exemples simples qui peuvent être utilisés (tous n'ont pas été essayés) En gros, défini sur "SearchSourceBuilder"

Requête de plage (spécifier la période)

Obtenu du "2019-12-12T 00:10:30" au "2019-12-13T 00:10:31" au Japon, heure

SearchSourceBuilder searchBuilder = SearchSourceBuilder.searchSource();

QueryBuilder query = QueryBuilders
       .rangeQuery("post_date")
       .from("2019-12-12T00:10:30")
       .to("2019-12-13T00:10:31")
       .timeZone("+09:00");

searchBuilder.query(query);

Il faut faire attention si vous spécifiez comme suit Aller de "2019-12-09T 00: 00: 00.000" à "2019-12-13T 23: 59: 59.999"

QueryBuilder query = QueryBuilders
       .rangeQuery("post_date")
       .from("2019-12-12")
       .to("2019-12-13")
       .timeZone("+09:00");

searchBuilder.query(query);

Pour obtenir des données pour 12 jours seulement:

"Inclure inférieur" pour inclure de: vrai "IncludeUpper" à inclure à: true

QueryBuilder query = QueryBuilders
       .rangeQuery("post_date")
       .from("2019-12-12")
       .to("2019-12-13")
    .includeLower(true)
    .includeUpper(false)
       .timeZone("+09:00");

searchBuilder.query(query);

Match Query La requête pour la recherche en texte intégral est ci-dessous

SearchSourceBuilder searchBuilder = SearchSourceBuilder.searchSource();

QueryBuilder query = QueryBuilders.matchQuery("message", "REST Level ");
QueryBuilder query = QueryBuilders.matchQuery("message", "Level REST");
QueryBuilder query = QueryBuilders.matchPhraseQuery("message", "REST Level");
//Puisqu'il s'agit d'une recherche de phrase, 0 éléments sont acquis
QueryBuilder query = QueryBuilders.matchPhraseQuery("message", "Level REST");

searchBuilder.query(query);

Term Query La requête Term qui est recherchée par correspondance exacte est la suivante

QueryBuilder query = QueryBuilders.termQuery("user", "qiita");

Bool Query(AND OR NOT)

Elastic Elastic SQL La description
must AND
filter AND Ignorer le score
should OR
mustnot NOT

AND Soit «doit» ou «filtrer» est acceptable

Un exemple de "filtre" ressemble à ceci

SearchSourceBuilder searchBuilder = SearchSourceBuilder.searchSource();

BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
QueryBuilder query1 = QueryBuilders.matchQuery("message", "JAVA");
QueryBuilder query2 = QueryBuilders.matchQuery("message", "REST");
boolQuery.filter(query1);
boolQuery.filter(query2);

searchBuilder.query(boolQuery);

OR

BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
QueryBuilder query1 = QueryBuilders.matchQuery("message", "JAVA");
QueryBuilder query2 = QueryBuilders.matchQuery("message", "REST");
boolQuery.should(query1);
boolQuery.should(query2);

NOT

BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
QueryBuilder query = QueryBuilders.termQuery("user", "qiita");
boolQuery.mustNot(query);

Comment rechercher au format JSON?

Vous pouvez également l'obtenir au format JSON comme indiqué ci-dessous. Search Template API

SearchTemplateRequest request = new SearchTemplateRequest();
request.setRequest(new SearchRequest("qiita"));

request.setScriptType(ScriptType.INLINE);
request.setScript(
                    "{" +
                            "  \"query\": { \"match\" : { \"{{field}}\" : \"{{value}}\" } }," +
                            "  \"size\" : \"{{size}}\"" +
                            "}");

Map<String, Object> scriptParams = new HashMap<>();
scriptParams.put("field", "message");
scriptParams.put("value", "REST");
scriptParams.put("size", 5);
request.setScriptParams(scriptParams);

SearchTemplateResponse response = client.searchTemplate(request, RequestOptions.DEFAULT);
SearchResponse searchResponse = response.getResponse();
SearchHit[] results = searchResponse.getHits().getHits();

Frozen indices Il peut être utilisé à partir de 6.8.1 "Client REST de haut niveau Java" Notez que cela n'est pas reflété lorsque "Index gelés" est implémenté dans Elastic saerch.

How to Search Freeze Index using Java High Level REST Client

SearchRequest request = new SearchRequest("qiita").source(searchBuilder);
request.indicesOptions(IndicesOptions.fromOptions(
                true,
                true,
                true,
                false,
                request.indicesOptions().allowAliasesToMultipleIndices(),
                request.indicesOptions().forbidClosedIndices(),
                request.indicesOptions().ignoreAliases(),
                true //← Définir si l'index figé peut être recherché ici true:Recherche
        ));

Matériel de référence

À la fin

Il y a peu d'articles japonais sur "Java High Level REST Client", et je lis souvent des articles en anglais et en chinois. Bien qu'il soit principalement écrit dans le document, après l'ajout de nouvelles fonctionnalités, il semble que "Java High Level REST Client" ne le supporte pas, vous devrez donc peut-être lire la source et les notes de version.

Demain, c'est @ NAO_MK2.

Recommended Posts

Conseils pour le client REST de haut niveau Java
Migrer du client de transport vers le client de niveau supérieur Rest
Astuces Java, astuces
Astuces Java
Client Java mqtt
Astuces Java - Modificateurs de classe StaticUtility
Astuces Java - Résumé de l'exécution de Spring
[Java] Server Client Communication 1 (inachevée)
[Java] Conseils pour l'écriture de la source