[JAVA] Création d'une série de plugins Elasticsearch (2) Recherche

Dans cette série, j'expliquerai la manière de base d'écrire un plugin pour Elastic search. Dernière fois a expliqué comment créer un plugin en gros en créant un plugin simple qui affiche Hello World. La partie 2 créera un plugin qui accepte les requêtes de recherche simples. La source créée peut être trouvée dans github (la précédente a été modifiée).

Objectif

Elasticsearch peut gérer la plupart des requêtes de recherche avec des requêtes au format JSON. Cependant, si elle est standard, les fonctions de maintenance telles que la suppression d'index seront visibles, et il n'est pas souhaitable d'accéder à Elasticsearch directement depuis le WEB. Par conséquent, normalement, Elasticsearch est utilisé comme une image comme une base de données sous la forme de WEB → serveur AP → Elasticsearch. De plus, Elasticsearch peut facilement garantir la disponibilité en utilisant un cluster, mais le serveur AP doit garantir la disponibilité par une méthode originale. Cela impose une lourde charge opérationnelle et augmente le nombre de cibles de surveillance. Si Elasticsearch peut avoir la fonction de serveur AP, il devrait être possible de créer une application qui répond à certaines exigences commerciales uniquement en gérant Elasticsearch. À partir de ce moment, nous vérifierons combien de choses peuvent être faites avec le plug-in dans le but d'avoir Elasticsearch avoir un serveur AP. Commençons par créer une API REST qui effectue une recherche en texte intégral sur le champ "texte" d'un document avec des paramètres de requête (texte).

Aperçu de la mise en œuvre

Le cadre du plug-in est le même que la dernière fois. La différence est que RestHandler envoie une "demande de recherche" au nœud d'index. Je génère une «requête de recherche» pour un nœud d'index à partir d'une requête REST, mais je peux facilement générer une «requête de recherche» à partir d'une requête REST au format JSON d'Elasticsearch. Cette fois, je vais l'utiliser.

Environnement d'exploitation

C'est presque la même chose que la dernière fois, mais j'ai utilisé la version 6.1 de Gradle car elle était sortie.

Notation dans l'article

Préparation préalable

--Installez Elasticsearch version OSS Développer vers [ELASTICSEARCH_DIR] --Installez Gradle Release version Développez jusqu'à [GRADLE_DIR]

Préparation du projet

Dernière fois Utilisez le projet créé.

Préparation de la source du plug-in

Créez un utilitaire pour générer des requêtes au format JSON.

Il est plus facile de voir lors du chargement de modèles à partir d'un fichier, mais Elasticsearch a un accès assez restreint aux API standard de Java à partir de plugins. Vous pouvez le rendre accessible dans les paramètres, mais cette fois, nous l'intégrerons dans la source. J'écrirai sur l'assouplissement des restrictions d'accès à l'API à partir de la prochaine fois.

QueryTemplate.java


package taka8.elasticsearch.rest;

public class QueryTemplate {

//	{
//	  "query" : {
//	    "match" : {
//	      "text" : {
//	        "query" : "[[text]]",
//	        "operator" : "and"
//	      }
//	    }
//	  }
//	}
	private static final String TEXT_ONLY = "{\"query\":{\"match\":{\"text\":{\"query\":\"[[text]]\",\"operator\":\"and\"}}}}";

	public static String getTextOnly(String text) {
		return QueryTemplate.TEXT_ONLY.replace("[[text]]", text);
	}
}

Créer un RestHandler

TextOnlySearchAction.java


package taka8.elasticsearch.rest;

import static org.elasticsearch.rest.RestRequest.Method.GET;

import java.io.IOException;

import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.node.NodeClient;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.xcontent.DeprecationHandler;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.rest.BaseRestHandler;
import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.rest.action.RestStatusToXContentListener;
import org.elasticsearch.search.builder.SearchSourceBuilder;

//RestHandler qui accepte l'API REST est facile à créer en héritant de BaseRestHandler
public class TextOnlySearchAction extends BaseRestHandler {

	public TextOnlySearchAction(final RestController controller) {
		assert controller != null;
		//Définissez le chemin pour accepter la demande.
		controller.registerHandler(GET, "/{index}/search_text", this);
	}

	//Définissez le nom de RestHandler.
	//Rendez le nom facile à voir pour les gens.
	//Utilisé dans les API qui retournent l'utilisation
	@Override
	public String getName() {
		return "search_text_action";
	}

	@Override
	protected RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException {
		SearchRequest searchRequest = new SearchRequest();
		request.withContentOrSourceParamParserOrNull(parser -> _parseSearchRequest(searchRequest, request, parser));
		return channel -> {
			//Générez un écouteur qui crée une valeur de retour d'API REST à partir des résultats de la recherche.
			//Ici, c'est un Listener standard qui renvoie le résultat de la recherche tel quel.
			RestStatusToXContentListener<SearchResponse> listener = new RestStatusToXContentListener<>(channel);
			//Lancez une requête au nœud d'index. Elasticsearch garantit les performances et la disponibilité de la recherche en divisant l'index et en l'organisant sur plusieurs nœuds.
			//Par conséquent, il est nécessaire d'envoyer une demande du nœud qui accepte la demande REST au nœud qui effectue réellement la recherche.
			client.search(searchRequest, listener);
		};
	}

	//Initialisez la demande de recherche sur le nœud d'index à partir de l'entrée REST.
	private void _parseSearchRequest(SearchRequest searchRequest, RestRequest request,
			XContentParser requestContentParser) throws IOException {
		if (searchRequest.source() == null) {
			searchRequest.source(new SearchSourceBuilder());
		}
		//Générez une requête de recherche au format JSON Elasticsearch à partir du paramètre de texte de la requête.
		String source = QueryTemplate.getTextOnly(request.param("text"));
		//Analyseur de requêtes de recherche au format JSON.
		XContentParser parser = XContentType.JSON.xContent().createParser(request.getXContentRegistry(),
				DeprecationHandler.THROW_UNSUPPORTED_OPERATION, source);
		searchRequest.source().parseXContent(parser);
		searchRequest.indices(Strings.splitStringByCommaToArray(request.param("index")));
	}

}

Contrôle de fonctionnement

Déployer

Suivez la procédure de vérification du fonctionnement de Dernière fois pour installer Elasticsearch.

Enregistrement des documents à rechercher

POST le document au format json à l'URL suivante à l'aide d'un outil qui peut émettre une requête POST. http://localhost:9200/test/_bulk

{"create": {"_id": "1"}}
{"text": "Monte dans la voiture"}
{"create": {"_id": "2"}}
{"text": "Descendre du vélo"}

Vérification d'écran

Accédez à "http : // localhost: 9200 / test / search_text? Text = car" dans votre navigateur et vérifiez que les documents contenant "car" sont recherchés comme indiqué ci-dessous (les formats JSON suivants). Faire).

{
  "took": 43,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 1,
      "relation": "eq"
    },
    "max_score": 1.0921589,
    "hits": [
      {
        "_index": "test",
        "_type": "_doc",
        "_id": "1",
        "_score": 1.0921589,
        "_source": {
          "text": "Monte dans la voiture"
        }
      }
    ]
  }
}

Épilogue

J'ai fait une demande au format JSON à partir d'une requête avec un plug-in et j'ai confirmé qu'elle pouvait être recherchée correctement en l'utilisant. Cela semble satisfaire la recherche avec les exigences commerciales standard. Ensuite, essayez de générer une valeur de retour qui répond aux besoins de votre entreprise.

Recommended Posts

Création d'une série de plugins Elasticsearch (2) Recherche
Création d'index Elastic Search à partir de Java
[Rails] Création d'un champ de recherche
Créez votre propre plugin Elasticsearch