Préface
Dans l'article précédent, Springboot, Mybatis, Druid et Pagehelper ont été intégrés et les opérations de plusieurs sources de données ont été implémentées. Cet article présente et utilise principalement Elastisarch, le moteur de recherche le plus populaire, et l'utilise en combinaison avec Springboot.
Introduction à Elasticsearch
Elasticsearch est un serveur de recherche basé sur Lucene. Il résume en fait Lucene et fournit l'interface de fonctionnement de l'API REST. Elasticsearch est un moteur de recherche et d'analyse en texte complet open source hautement évolutif qui peut être utilisé pour stocker, rechercher et analyser rapidement les mégadonnées.
Les principales caractéristiques d'Elasticsearch: distribuée, haute disponibilité, écriture asynchrone, multi-API, axée sur le document.
Elasticsearch Core Concepts: quasi-temps, cluster, nœud (données de sauvegarde), index, fragment (fragments d'index de découpage), répliques (le tranchage peut définir plusieurs répliques). Il peut rapidement stocker, rechercher et analyser des quantités massives de données.
Elasticsearch Cas d'utilisation: Wikipedia, Stack Overflow, GitHub, etc.
Springboot intègre Elasticsearch
Avant d'utiliser Springboot pour intégrer Elasticsearch, nous devons comprendre la relation entre eux.
| Spring Boot Version (X) | Spring Data Elasticsearch Version (Y) | Version Elasticsearch (Z) |
|---|---|---|
| x <= 1.3.5 | y <= 1.3.4 | z <= 1,7,2 * |
| x> = 1.4.x | 2.0.0 <= y <5.0.0 ** | 2.0.0 <= z <5.0.0 ** |
La version de Springboot que nous utilisons ici est 1.5.9, et la version d'Elasticsearch est 2.3.5.
En utilisant Springboot pour intégrer Elasticsearch, il est généralement encapsulé à l'aide de SpringData, puis l'interface de couche DAO hérite de la classe ElasticSearchRepostory. Cette classe met en œuvre de nombreuses méthodes, telles que la méthode CRUD couramment utilisée.
Utilisation de Springdata
Tout d'abord, faites des préparations pertinentes avant utilisation.
La configuration de Maven est la suivante:
<dependency> <proupId> org.springframework.boot </proupId> <ArtifactId> printemps-boot-starter-web </ artifactive> <version> 1.5.9.release </ version> </pedency> <dependency> <proupId> org.springframework.boot </prounid> artifactive> spring-boot-starter-data-data-datasearch </proditectid> <version> 1.5.9.release </ version> </Dependance>
Configuration de l'application.properties
printemps.data.ellasticsearch.repositories.enabled = truspring.data.elasticsearch.cluster-nodes = 127.0.0.1 /: 9300
Remarque: 9300 est le port du client Java. 9200 est une interface qui prend en charge RESTful HTTP.
Plus de configurations:
printemps.data.ellasticsearch.cluster-name Elasticsearch Cluster Nom. (Par défaut: elasticsearch)
printemps.data.ellasticsearch.cluster-nodes Liste des adresses de nœud de cluster, séparées par des virgules. S'il n'est pas spécifié, démarrez un nœud client.
printemps.data.ellasticsearch.propertie est utilisé pour configurer des propriétés supplémentaires du client.
printemps.data.ellasticsearch.repositries.enabled Activer le référentiel Elasticsearch. (Par défaut: true.)
Écriture de code
Classe d'entité
@Document (indexName = "userIndex", type = "user") public class utilisateur implémente serializable {/ ** * * / private static final long SerialVersionUID = 1l; / ** numéro * / ID long privé; / ** nom * / nom de chaîne privée; / ** Âge * / Age entier privé; / ** Description * / String privé Description; / ** Temps de création * / Private String CreateTm; // Getter et Setter omis}Lorsque vous utilisez SpringData, il doit définir IndexName et saisir la classe d'entité. Par rapport aux bases de données traditionnelles, elle équivaut aux bibliothèques et aux tables.
Il convient de noter que le nom d'index et le type doivent être en minuscules !!!
Couche DAO
Interface publique UserDao étend ElasticSearchRepository <utilisateur, long> {}La couche DAO est relativement simple ici, il suffit de hériter de la classe ElasticSearchRepostory. Les principales méthodes sont la sauvegarde, la suppression et la recherche. La méthode de sauvegarde est tout à fait comme insérer et mettre à jour. S'il n'y a pas, il sera ajouté et s'il y en a un, il sera couvert. La méthode de suppression est principalement de supprimer les bibliothèques de données et d'index. Quant à la recherche, il s'agit d'une requête, y compris certaines requêtes couramment utilisées, telles que la pagination, les poids, etc.
Couche de service
@ServicePublic Class UserserServiceIMPL implémente UserService {@Autowired Private UserDao UserDao; @Override public boolean insert (utilisateur utilisateur) {booléen falg = false; essayez {userdao.save (utilisateur); falg = true; } catch (exception e) {e.printStackTrace (); } return falg; } @Override public list <User> search (string searchContent) {queryStringQueryBuIlder builder = new QueryStringQueryBuilder (SearchContent); System.out.println ("Instruction de requête:" + Builder); ITable <User> searchResult = userdao.search (builder); Iterator <User> iterator = searchResult.Itorator (); List <ser user> list = new ArrayList <User> (); while (iterator.hasnext ()) {list.add (iterator.next ()); } Retour List; } @Override public list <ser utilisateur> SearchUser (entier PageNumber, entier pagesize, string searchContent) {// paramètres de pagination pagable pagable = new pageRequest (pageNumber, pageSize); QueryStringQueryBuilder Builder = new QueystringQueryBuilder (SearchContent); SearchQuery searchQuery = new NativesearchQueryBuIlder (). AvecPagable (pagable) .WithQuery (Builder) .Build (); System.out.println ("Instruction de requête:" + SearchQuery.getQuery (). ToString ()); Page <User> SearchPageResults = UserDao.Search (SearchQuery); return searchPageresults.getContent (); } @Override public list <ser utilisateur> searchUserByweight (string searchContent) {// Query Selon les poids fonctions de fonctions oriento ScorefunctionBuilders.WeightFactorFunction (10)) .add (queryBuilders.boolQuery (). Devrait (queryBuilders.matchQuery ("Description", SearchContent)), ScoreFunctionBuilders.WeightFactorFunction (100)). SetMinscore (2); System.out.println ("Instruction de requête:" + FunctionScoreQueryBuilder.ToString ()); ITable <User> searchResult = userdao.search (fonctionScoreQueryBuilder); Iterator <User> iterator = searchResult.Itorator (); List <ser user> list = new ArrayList <User> (); while (iterator.hasnext ()) {list.add (iterator.next ()); } Retour List; }}Ici, j'ai simplement écrit plusieurs méthodes, la méthode principale est la requête. Les requêtes incluent la recherche en texte intégral, la requête de pagination et la requête de poids. Ce qui doit être expliqué, c'est la requête de poids. Plus le score de poids est élevé, plus le résultat de la requête est élevé. Si aucun score n'est défini pour d'autres données, leur score par défaut est 1. Si vous ne souhaitez pas interroger ces instructions, utilisez simplement SetMinscore pour le définir à plus de 1.
Tests de code
Appelez l'interface pour ajouter des données
Nouvelles données:
Post http: // localhost: 8086 / api / utilisateur {"id": 1, "name": "Zhang San", "Age": 20, "Description": "Zhang San est un ingénieur de développement Java", "CreateTm": "Nom 2018-4-25 Si est un ingénieur de test "," CreateTm ":" 1980-2-15 19:01:32 "} {" id ": 3," nom ":" Wang Wu "," Age ": 25," Description ":" Wang Wu est un ingénieur d'opération et de maintenance "," CreateTm ":" 2016-8-21 06:11:32 "} Effectuer une requête en texte intégral
demander
http: // localhost: 8086 / api / utilisateur? SearchContent = ingénieur
retour
[{"id": 2, "nom": "li si", "âge": 14, "Description": "Li si est un ingénieur de test", "CreateTm": "1980-2-15 19:01:32"}, {"id": 1, "nom": "Zhang San", "Age": "Description": "Zhang San est un ingénieur de développement Java": "Createrm": "Zhang San est un ingénieur de développement Java", "Createrm": ":" Créerm ":": Créerm ":": Créerme " "2018-4-25 11:07:42"}, {"id": 3, "nom": "wang wu", "age": 25, "Description": "Wang wu est un ingénieur d'opération et de maintenance", "CreateTm": "2016-8-21 06:11:32"}] Effectuer une requête de pagination
demander
http: // localhost: 8086 / api / utilisateur? pageNumber = 0 & pagesize = 2 & searchContent = ingénieur
retour
[{"id": 2, "nom": "li si", "âge": 14, "Description": "Li si est un ingénieur de test"}, {"id": 1, "nom": "Zhang San", "Age": 20, "Description": "Zhang San est un ingénieur de développement Java"}] Effectuer une requête de poids
demander
http: // localhost: 8086 / api / user2? SearchContent = li si
retour
[{"id": 2, "nom": "li si", "âge": 24, "Description": "Li si est un ingénieur de test", "CreateTm": "1980-2-15 19:01:32"}]La déclaration d'impression de la requête de poids:
Instruction de requête: {{"function_score": {"fonctions": [{"filter": {"bool": {"bool": {"devrait": {"correspond": {"name": {"Query": "li si", "type": "boolean"}}}}}}}}, " {"bool": {"devrait": {"correspond": {"Description": {"Query": "li si", "type": "boolean"}}}}}}, "poids": 100.0}], "min_score": 2.0}}Remarque: Dans le test, puisque le poids minimum de Setminscore est défini pour être divisé en 2, les données non pertinentes ne seront pas affichées. Si vous souhaitez l'afficher, supprimez-le simplement dans le code.
Après avoir ajouté de nouvelles données, vous pouvez entrer: http: // localhost: 9200 / _plugin / head / in the Browser
Cliquez ensuite sur la requête de base pour afficher les données ajoutées. Si vous souhaitez utiliser la requête de déclaration, vous pouvez coller la déclaration de requête imprimée par la console dans le programme à l'interface de requête pour la requête!
Remarque: J'ai installé Elasticsearch ici sur Windows et installé la tête du plugin ES. Les étapes d'installation spécifiques sont à la fin de l'article.
En plus de SpringData, il existe en fait d'autres méthodes pour faire fonctionner Elasticsearch.
Par exemple, utilisez l'API Native Elasticsarch et utilisez la classe TransportClient pour l'implémenter.
Ou utilisez-le pour encapsuler au printemps, injectez simplement le haricot dans la couche de service.
Exemple:
@Autowired elasticsearchTemplate elasticsearchTemplate;
Cependant, les méthodes ci-dessus ont leurs limites, c'est-à-dire que la version d'Elasticsearch est modifiée, l'API Java pertinente s'adapte également constamment, c'est-à-dire, une fois que la version du serveur d'Elasticsearch est modifiée, le code du client peut devoir être réécrit.
Par conséquent, il introduit un outil tiers très utile. Il résume Elasticsearch et comble l'écart dans le client d'interface Httprest Elasticsearch. Il convient aux versions Elasticsearch 2.x ou supérieures, et il n'est pas nécessaire de modifier le code en raison du changement de version du serveur Elasticsearch!
Jestclient
Ajoutez d'abord les dépendances suivantes dans Maven:
<dependency> <proupId> io.searchbox </rom groupeid> <Artifactid> jest </ artifactid> <version> 5.3.3 </-version> </dependency>
Écrivez ensuite le code de test pertinent.
Les commentaires dans le code doivent être très complets, donc je ne parlerai pas trop du code ici.
import java.util.arraylist; import java.util.list; import org.elasticsearch.index.query.querybuilders; import org.ellasticsearch.search.builder.searchsourcebuilder; import com.pancm.pojo.user; import io.searchbox.client.jestclient; importation; import; io.searchbox.client.jestclientfactory; import io.searchbox.client.jestresult; import io.searchbox.client.config.httpclientconfig; import io.searchbox.core.bulk; import io.searchbox.core.bulkresult; import io.searchbox.core io.searchbox.core.DocumentResult; import io.searchbox.core.index; importer io.searchbox.core.search; import io.searchbox.indices.createIndex; import io.searchbox.indices.deleteIndex; import io.searchbox.indices.mapping.getMapping; import io.ssearchbox.inds.mapping. JESTTEST {JESTCLIENT STATIQUE PRIVÉE JESTCLIENT; private static string indexName = "userIndex"; // private static string indexName = "userIndex2"; chaîne statique privée typename = "utilisateur"; chaîne statique privée Elastips = "http://192.169.2.98:9200"; // String statique privé Elastips = "http://127.0.0.1:9200"; public static void main (String [] args) lève une exception {jestClient = getJestClient (); insertBatch (); Serach1 (); Serach2 (); Serach3 (); jestclient.close (); } private static jestClient getJestClient () {jestClientFactory factory = new JestClientFactory (); factory.sethttpclientconfig (new httpclientconfig.builder (elastips) .ConnTimeout (60000) .readTimeout (60000) .MultithreDed (true) .build ()); return factory.getObject (); } public static void insertBatch () {list <objet> objs = new ArrayList <Bject> (); objs.add (nouvel utilisateur (1L, "Zhang San", 20, "Zhang San est un ingénieur de développement Java", "2018-4-25 11:07:42")); objs.add (nouvel utilisateur (2L, "Li si", 24, "Li si est un ingénieur de test", "1980-2-15 19:01:32")); objs.add (nouvel utilisateur (3L, "Wang Wu", 25, "Wang Wu est un ingénieur d'opération et de maintenance", "2016-8-21 06:11:32")); Résultat booléen = false; try {result = insertBatch (jestClient, indexName, typename, objs); } catch (exception e) {e.printStackTrace (); } System.out.println ("Lot New:" + Result); } / ** * Recherche de texte intégral * / public static void Serach1 () {String Query = "Engineer"; essayez {searchsourceBuilder searchSourceBuilder = new SearchSourceBuilder (); SearchsourceBuilder.Query (queryBuilders.QuerystringQuery (Query)); // Paramètres de page SearchSourceBuilder.from (0) .Size (2); System.out.println ("Instruction de requête de recherche en texte complet:" + SearchsourceBuilder.ToString ()); System.out.println ("La recherche de texte complet renvoie Résultat:" + Search (JestClient, indexName, typename, searchSourceBuilder.ToString ())); } catch (exception e) {e.printStackTrace (); }} / ** * Recherche exacte * / public static void Serach2 () {try {searchSourceBuilder SearchSourceBuilder = new SearchSourceBuilder (); SearchsourceBuilder.Query (QueryBuilders.termQuery ("Age", 24)); System.out.println ("Instruction de requête de recherche exacte:" + SearchsourceBuilder.ToString ()); System.out.println ("Exact Search Returns Résultat:" + Search (JestClient, indexName, typename, SearchSourceBuilder.ToString ())); } catch (exception e) {e.printStackTrace (); }} / ** * Recherche d'intervalle * / public static void Serach3 () {String createTm = "createTm"; Chaîne de = "2016-8-21 06:11:32"; String to = "2018-8-21 06:11:32"; essayez {searchsourceBuilder searchSourceBuilder = new SearchSourceBuilder (); SearchsourceBuilder.Query (queryBuilders.RangeQuery (CreateTm) .gte (From) .lte (à)); System.out.println ("Énoncé de recherche d'intervalle:" + SearchsourceBuilder.ToString ()); System.out.println ("Interval Search Retains Résultat:" + Search (JestClient, indexName, typename, searchSourceBuilder.ToString ())); } catch (exception e) {e.printStackTrace (); }} / ** * Create index * @param indexName * @return * @throws exception * / public boolean createIndex (jestClient jestClient, String indexName) lève exception {jestresult jr = jestclient.execute (new CreateIndex.Builder (indexName) .Build ()); return jr.issucceeded (); } / ** * Nouvelles données * @param indexname * @param typename * @param source * @return * @throws exception * / public boolean insert (jestclient jestclient, string indexName, String typename, string source) lance exception {putmapping putmappy = new putmapping.builder (indexName, typename, source) .build (); JestResult Jr = jestClient.Execute (putMapping); return jr.issucceeded (); } / ** * Données de requête * @param indexname * @param typename * @return * @throws exception * / public static static getIndexmapping (jestclient jestclient, string indexName, string typename) lève exception {getMapping getMapping = new getMapping.builder (). JestResult Jr = jestClient.Execute (getMapping); return jr.getJSontring (); } / ** * Ajouter des données en lots * @param indexname * @param typename * @param objs * @return * @throws exception * / public static boolean insertbatch (jestclient jestclient, string indexName, string typename, list <object> objs) lance l'exception {bulk.builder bulk = new Bulk.builder (). DefaultIndex (indexName) .DefaultType (typename); pour (objet obj: objs) {index index = new index.builder (obj) .build (); bulk.addaction (index); } BulkResult br = jestclient.execute (bulk.build ()); Retour br.issuCceedEd (); } / ** * Recherche de texte intégral * @param indexname * @param typename * @param query * @return * @throws exception * / public static string search (jestclient jestclient, string indexName, string typename, string retere) exception {search search.builder (werry) .adDindex (indexName) .AddType (TapEname). JestResult jr = jestClient.Execute (Search); // System.out.println ("-" + jr.getjSontring ()); // System.out.println ("-" + jr.getsourceSobject (user.class)); return jr.getsourceSsstring (); } / ** * Delete index * @param indexname * @return * @throws exception * / public boolean Delete (jestclient jestClient, String indexName) lève l'exception {jestResult jr = jestclient.execute (new DeleteIndex.Builder (indexName) .Build ()); return jr.issucceeded (); } / ** * Delete Data * @param indexname * @param typename * @param id * @return * @throws exception * / public boolean delete (jestclient jestClient, String indexName, String typEname, String id) lance l'exception {documentResult dr = jestClient.Execute (new Delete.Builder (id) .Index (indexName) .Type (typename) .build ()); Retour Dr.SUSUCEDED (); }Remarque: Avant les tests, expliquons d'abord que la version Elasticsearch installée sur le système Windows local est 2.3.5 et que la version Elasticsearch installée sur le serveur Linux est 6.2.
Résultats des tests
Recherche en texte intégral
Instruction de requête de recherche en texte complet: {"From": 0, "Size": 2, "Query": {"Query_string": {"Query": "ingénieur"}}} Recherche de texte complet Retour: {"id": 1, "nom": "Zhang SAN", "Age": 20, "Description": "Zhang San est un développement java java Ingénieur "," CreateTm ":" 2018-4-25 11:07:42 "}, {" id ": 2," nom ":" Li si "," Age ": 24," Description ":" Li Si est un ingénieur de test "," CreateTm ":" 1980-2-15 19:01:32 "}Match Search
Instruction de requête de recherche précise: {"Query": {"Term": {"Age": 24}}} Retours de recherche précis Retours: {"id": 2, "name": "li si", "Age": 24, "Description": "Li si est un ingénieur de test", "CreateTm": "1980-15 19:01:32"}Recherche d'intervalle de temps
Instruction de recherche d'intervalle: {"Query": {"Range": {"CreateTm": {"From": "2016-8-21 06:11:32", "to": "2018-8-21 06:11:32", "include_lower": true, "include_upper": true}}}} intervalle de recherche RETOURS: {"id": "Nom": "zhn intervalle RETOURS: {" id ":" Nom ":" zhnter les résultats de l'intervention: {"Id": "Nom": "Zhn Interval Returns Retour: {" id ":" Nom ":" Zhn Intercal San "," Age ": 20," Description ":" Zhang San est un ingénieur de développement Java "," CreateTm ":" 2018-4-25 11:07:42 "}Après avoir ajouté de nouvelles données, nous pouvons aller à Linux Kibana pour mener des requêtes connexes, et les résultats de la requête sont les suivants:
Remarque: Kibana est un logiciel open source dans Elk. Kibana fournit des interfaces Web conviviales pour l'analyse des journaux pour Logstash et ElasticSearch pour aider à résumer, analyser et rechercher des journaux de données importants.
Les résultats renvoyés par le test dans le code ci-dessus sont conformes à nos attentes. Parmi eux, seule une petite partie de Jestclient est utilisée. Pour plus d'utilisation, vous pouvez consulter la documentation officielle de JestClient.
Installez Elasticsearch sur Windows
1. Préparation du document
Télécharger l'adresse: https://www.elastic.co/downloads
Sélectionnez la version liée à Elasticsearch, puis sélectionnez le fichier zip de nom de suffixe à télécharger, puis décompressez-le après le téléchargement.
2. Démarrer Elasticsearch
Allez dans le répertoire des bacs et exécutez elasticsearch.bat
Entrez ensuite: localhost: 9200 sur le parcours
Afficher avec succès l'interface signifie le succès!
3. Installez le plug-in ES
Installation de tête d'interface de gestion Web
Entrez le répertoire bac, ouvrez CMD et entrez l'interface DOS
Entrez: plugin install mobz/elasticsearch-head
Faire un téléchargement
Après avoir réussi à télécharger, entrez: http: // localhost: 9200 / _plugin / head /
Si l'interface s'affiche, l'installation réussira!
4. Service d'enregistrement
Entrez le répertoire bac, ouvrez CMD et entrez l'interface DOS
Entrer:
service.bat installService.bat start
Après le succès, entrez
services.msc
Passez à l'interface de service de service pour afficher directement l'état en cours d'exécution des ES!
autre
Adresse API du site Web officiel d'Elasticsearch:
https://www.elastic.co/guide/en/elasticsearch/client/java-api/2.3/index.html
Adresse JestClientGithub:
https://github.com/searchbox-io/jest (téléchargement local)
J'ai mis le projet sur Github.
https://github.com/xuwujing/springboot (téléchargement local)
Résumer
Ce qui précède est l'intégralité du contenu de cet article. J'espère que le contenu de cet article a une certaine valeur de référence pour l'étude ou le travail de chacun. Si vous avez des questions, vous pouvez laisser un message pour communiquer. Merci pour votre soutien à wulin.com.