Leitfaden zur Elasticsearch in Java

1. Übersicht

In diesem Artikel werden wir uns mit einigen Schlüsselkonzepten im Zusammenhang mit Volltextsuchmaschinen befassen, wobei der Schwerpunkt auf Elasticsearch liegt.

Da es sich um einen Java-orientierten Artikel handelt, werden wir keine detaillierte Schritt-für-Schritt-Anleitung zum Einrichten von Elasticsearch geben und zeigen, wie es unter der Haube funktioniert. Stattdessen zielen wir auf den Java-Client ab und erläutern, wie die Hauptfunktionen wie Indexieren , Löschen , Abrufen und Suchen verwendet werden .

2. Setup

Der Einfachheit halber verwenden wir ein Docker-Image für unsere Elasticsearch-Instanz, obwohl jede Elasticsearch-Instanz, die Port 9200 überwacht, ausreicht .

Wir starten zunächst unsere Elasticsearch-Instanz:

docker run -d --name es762 -p 9200:9200 -e "discovery.type=single-node" elasticsearch:7.6.2

Standardmäßig überwacht Elasticsearch den 9200-Port auf anstehende HTTP-Abfragen. Wir können überprüfen, ob es erfolgreich gestartet wurde, indem wir die URL // localhost: 9200 / in Ihrem bevorzugten Browser öffnen :

{ "name" : "M4ojISw", "cluster_name" : "docker-cluster", "cluster_uuid" : "CNnjvDZzRqeVP-B04D3CmA", "version" : { "number" : "7.6.2", "build_flavor" : "default", "build_type" : "docker", "build_hash" : "2f4c224", "build_date" : "2020-03-18T23:22:18.622755Z", "build_snapshot" : false, "lucene_version" : "8.4.0", "minimum_wire_compatibility_version" : "6.8.0", "minimum_index_compatibility_version" : "6.8.0-beta1" }, "tagline" : "You Know, for Search" }

3. Maven-Konfiguration

Nachdem wir unseren grundlegenden Elasticsearch-Cluster eingerichtet haben, können wir direkt zum Java-Client springen. Zunächst muss die folgende Maven-Abhängigkeit in unserer Datei pom.xml deklariert sein :

 org.elasticsearch elasticsearch 7.6.2 

Sie können jederzeit die neuesten Versionen von Maven Central über den zuvor angegebenen Link überprüfen.

4. Java API

Bevor wir direkt mit der Verwendung der wichtigsten Java-API-Funktionen beginnen, müssen wir den RestHighLevelClient initiieren :

ClientConfiguration clientConfiguration = ClientConfiguration.builder().connectedTo("localhost:9200").build(); RestHighLevelClient client = RestClients.create(clientConfiguration).rest();

4.1. Indizieren von Dokumenten

Mit der Funktion index () können Sie ein beliebiges JSON-Dokument speichern und durchsuchbar machen:

@Test public void givenJsonString_whenJavaObject_thenIndexDocument() { String jsonObject = "{\"age\":10,\"dateOfBirth\":1471466076564," +"\"fullName\":\"John Doe\"}"; IndexRequest request = new IndexRequest("people"); request.source(jsonObject, XContentType.JSON); IndexResponse response = client.index(request, RequestOptions.DEFAULT); String index = response.getIndex(); long version = response.getVersion(); assertEquals(Result.CREATED, response.getResult()); assertEquals(1, version); assertEquals("people", index); }

Beachten Sie, dass Sie jede JSON-Java-Bibliothek zum Erstellen und Verarbeiten Ihrer Dokumente verwenden können. Wenn Sie mit keinem dieser Dokumente vertraut sind, können Sie mithilfe der Elasticsearch-Helfer Ihre eigenen JSON-Dokumente erstellen :

XContentBuilder builder = XContentFactory.jsonBuilder() .startObject() .field("fullName", "Test") .field("dateOfBirth", new Date()) .field("age", "10") .endObject(); IndexRequest indexRequest = new IndexRequest("people"); indexRequest.source(builder); IndexResponse response = client.index(indexRequest, RequestOptions.DEFAULT); assertEquals(Result.CREATED, response.getResult());

4.2. Indizierte Dokumente abfragen

Nachdem wir ein typisiertes durchsuchbares JSON-Dokument indiziert haben, können wir mit der search () -Methode fortfahren und suchen :

SearchRequest searchRequest = new SearchRequest(); SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT); SearchHit[] searchHits = response.getHits().getHits(); List results = Arrays.stream(searchHits) .map(hit -> JSON.parseObject(hit.getSourceAsString(), Person.class)) .collect(Collectors.toList());

Die von der search () -Methode zurückgegebenen Ergebnisse werden als Treffer bezeichnet . Jeder Treffer bezieht sich auf ein JSON-Dokument, das einer Suchanforderung entspricht.

In diesem Fall enthält die Ergebnisliste alle im Cluster gespeicherten Daten. Beachten Sie, dass wir in diesem Beispiel die FastJson-Bibliothek verwenden, um JSON- Strings in Java-Objekte zu konvertieren .

Wir können die Anforderung erweitern, indem wir zusätzliche Parameter hinzufügen, um die Abfrage mithilfe der QueryBuilders- Methoden anzupassen :

SearchSourceBuilder builder = new SearchSourceBuilder() .postFilter(QueryBuilders.rangeQuery("age").from(5).to(15)); SearchRequest searchRequest = new SearchRequest(); searchRequest.searchType(SearchType.DFS_QUERY_THEN_FETCH); searchRequest.source(builder); SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);

4.3. Dokumente abrufen und löschen

Mit den Methoden get () und delete () können Sie ein JSON-Dokument mithilfe seiner ID aus dem Cluster abrufen oder löschen:

GetRequest getRequest = new GetRequest("people"); getRequest.id(id); GetResponse getResponse = client.get(getRequest, RequestOptions.DEFAULT); // process fields DeleteRequest deleteRequest = new DeleteRequest("people"); deleteRequest.id(id); DeleteResponse deleteResponse = client.delete(deleteRequest, RequestOptions.DEFAULT);

Die Syntax ist ziemlich einfach, Sie müssen nur den Index neben der Objekt-ID angeben.

5. QueryBuilders- Beispiele

Die QueryBuilders- Klasse bietet eine Vielzahl statischer Methoden, die als dynamische Matcher verwendet werden, um bestimmte Einträge im Cluster zu finden. Während Sie die search () -Methode verwenden, um nach bestimmten JSON-Dokumenten im Cluster zu suchen, können wir Abfrage-Builder verwenden, um die Suchergebnisse anzupassen.

Hier ist eine Liste der häufigsten Verwendungen der QueryBuilders- API.

Die matchAllQuery () -Methode gibt ein QueryBuilder- Objekt zurück, das allen Dokumenten im Cluster entspricht:

QueryBuilder matchAllQuery = QueryBuilders.matchAllQuery();

Die rangeQuery () entspricht Dokumente , in denen ein Feldwert innerhalb eines bestimmten Bereichs ist:

QueryBuilder matchDocumentsWithinRange = QueryBuilders .rangeQuery("price").from(15).to(100)

Durch Angabe eines Feldnamens - z. B. fullName und des entsprechenden Werts - z. B. John Doe - Die Methode matchQuery () stimmt alle Dokumente mit dem genauen Feldwert überein:

QueryBuilder matchSpecificFieldQuery= QueryBuilders .matchQuery("fullName", "John Doe");

Wir können auch die multiMatchQuery () -Methode verwenden, um eine Version der Übereinstimmungsabfrage mit mehreren Feldern zu erstellen:

QueryBuilder matchSpecificFieldQuery= QueryBuilders.matchQuery( "Text I am looking for", "field_1", "field_2^3", "*_field_wildcard");

Wir können das Caret-Symbol (^) verwenden, um bestimmte Felder zu verstärken .

In unserem Beispiel hat das Feld_2 einen Boost-Wert von drei, was es wichtiger macht als die anderen Felder. Beachten Sie, dass es möglich ist, Platzhalter- und Regex-Abfragen zu verwenden. Achten Sie jedoch beim Umgang mit Platzhaltern auf den Speicherverbrauch und die Verzögerung der Antwortzeit, da so etwas wie * _apples einen großen Einfluss auf die Leistung haben kann.

Der Wichtigkeitskoeffizient wird verwendet, um die Ergebnismenge der Treffer zu ordnen, die nach Ausführung der Methode earch () zurückgegeben werden.

Wenn Sie mit der Lucene- Abfragesyntax besser vertraut sind, können Sie die Methode simpleQueryStringQuery () verwenden, um Suchabfragen anzupassen:

QueryBuilder simpleStringQuery = QueryBuilders .simpleQueryStringQuery("+John -Doe OR Janette");

Wie Sie wahrscheinlich erraten können, können wir die Query Parser-Syntax von Lucene verwenden, um einfache, aber leistungsstarke Abfragen zu erstellen . Hier sind einige grundlegende Operatoren, die zusammen mit den AND / OR / NOT- Operatoren zum Erstellen von Suchanfragen verwendet werden können:

  • Der erforderliche Operator ( + ): erfordert, dass irgendwo in den Feldern eines Dokuments ein bestimmter Text vorhanden ist.
  • Der Verbotsoperator ( - ): schließt alle Dokumente aus, die ein nach dem Symbol ( - ) deklariertes Schlüsselwort enthalten .

6. Fazit

In diesem kurzen Artikel haben wir gesehen, wie Sie die Java-API von ElasticSearch verwenden, um einige der allgemeinen Funktionen von Volltextsuchmaschinen auszuführen.

Sie können das in diesem Artikel bereitgestellte Beispiel im GitHub-Projekt überprüfen.