L'article précédent a présenté qu'ElasticSearch utilise le référentiel et ElasticSearchTemplate pour créer des conditions de requête complexes, et introduit brièvement la fonction d'Elasticsearch pour utiliser l'emplacement géographique.
Dans cet article, jetons un coup d'œil à la fonction d'utiliser Elasticsearch pour compléter la grande question de données à proximité et rechercher des données dans la plage de N-mètre.
Préparer l'environnement
Le test natif utilise la dernière version 5.5.1 Elasticsearch, Springboot1.5.4 et Spring-Data-Elasticsearch2.1.4.
Créez un nouveau projet Springboot, consultez Elasticsearch et Web.
Le fichier POM est le suivant
<? xml version = "1.0" Encoding = "utf-8"?> <project xmlns = "http://maven.apache.org/pom/4.0.0" xmlns: xsi = "http://www.w3.org/2001/xmlschema-instance" XSI: ScheMalocation = "http://maven.apache.org/pom/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelversion> 4.0.0 </mackversion> <proupId> comidianyalei </prouverId> <ArtifActid> ElassicSearch> COMIANDEI </ / GroupId> <ArtifActid> ElasricSearc <version> 0.0.1-snapshot </packing> <packaging> jar </packaging> <name> elasticsearch </name> <description> Project de démonstration pour Spring Boot </ Description> <parent> <proupId> org.springframework.boot </proncId> <Artifactid> printemps-boot-starter-parent </ artifactid> <version> <! - Recherche parent du référentiel -> </parent> <properties> <project.build.sourceencoding> utf-8 </project.build.sourceencoding> <project.reportting.outputending> utf-8 </project.report.outputerSice> <java.version> 1.8 </java.version> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <GroupId> org.springframework.boot </proupId> <ArtifActid> Spring-Boot-starter-test </ artifactid> <ccope> test </cope> </dependency> <dependency> <proupId> com.sun.jna </proped> <ptetifactid> JNA </ artifactid> <version> 3.0.9 </ version> <flugins> <glugin> <groupId> org.springframework.boot </prômId> <Artifactid> Spring-Boot-Maven-Plugin </ ArfactId> </Glugin> </Glugins> </Duild> </ Project>
Créer une nouvelle personne de classe de modèle
Package com.tianyalei.ellasticsearch.model; import org.springframework.data.annotation.id; import org.springframework.data.ellasticsearch.annotations.Document; import org.springframework.data.ellasticsearch.annotations.geOPointfield; import java.io.serializable; / ** * Classe du modèle * / @Document (indexName = "Elastic_Search_Project", type = "Person", indexStoreType = "FS", Shards = 5, répliques = 1, RefreshInterval = "- 1") La classe publique implémente Serializable {@Id Private int id; nom de chaîne privé; téléphone de chaîne privé; / ** * Emplacement géographique Latitude et longitude * Latitude, Lon Longitude "40.715, -74.011" * Si vous utilisez un tableau, l'inverse est vrai [-73.983, 40.719] * / @geopointfield privé de chaîne privée; public int getID () {return id; } public void setid (int id) {this.id = id; } public String getName () {Nom de retour; } public void setName (string name) {this.name = name; } public String gephone () {return téléphone; } public void setphone (String Phone) {this.phone = téléphone; } public String getAddress () {return adresse; } public void setAddress (adresse de chaîne) {this.address = adresse; }} J'utilise le champ d'adresse pour représenter la position de latitude et de longitude. Notez que l'utilisation de String [] et de la chaîne sont différentes lors de la désignation de latitude et de longitude, consultez les commentaires.
import com.tianyalei.elasticsearch.model.person; import org.springframework.data.ellasticsearch.repository.ellasticsearchrepository; Interface publique PersonRepository étend ElasticsearchRepository <Person, Integer> {} Jetez un œil à la classe de service et remplissez la fonction d'insertion des données de test. J'ai mis la fonction de requête dans le contrôleur. Par souci de commodité, il doit être placé normalement dans le service.
Package com.tianyalei.ellasticsearch.service; import com.tianyalei.elasticsearch.model.person; import com.tianyalei.ellasticsearch.repository.personRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.ellasticsearch.core.ElasticSearchTemplate; import org.springframework.data.ellasticsearch.core.query.indexQuery; import org.springframework.sterreotype.service; import java.util.arraylist; Importer java.util.list; @Service public class PersonService {@autowired PersonPository PersonPository; @Autowired elasticsearchTemplate elasticsearchTemplate; String final statique privé Person_index_name = "Elastic_Search_Project"; String final statique privé Person_index_type = "personne"; Public Add (personne personne) {return personRepository.save (personne); } public void bulkIndex (list <onon> PersonList) {int compter = 0; essayez {if (! elasticsearchTemplate.Indexexists (Person_index_name)) {elasticsearchTemplate.createIndex (Person_index_type); } List <DexQuery> Queries = new ArrayList <> (); pour (personne personne: PersonList) {INDEXQUERY INDEXQUERY = NEW INDEXQUERY (); INDEXQUERY.SETID (Person.getId () + ""); indexQuery.SetObject (personne); indexQuery.setIndexName (Person_index_name); indexQuery.setType (Person_index_type); // Les étapes ci-dessus peuvent également être utilisées pour construire en utilisant IndexQueryBuilder // IndexQuery index = new INDEXQUERYBUILDER (). WithId (Person.getId () + "") .WithObject (personne) .Build (); requêtes.add (indexQuery); if (compter% 500 == 0) {elasticsearchTemplate.bulkIndex (requêtes); requêtes.clear (); System.out.println ("BulkIndex Counter:" + Counter); } compteur ++; } if (quelles.size ()> 0) {elasticsearchTemplate.bulkIndex (requêtes); } System.out.println ("BulkIndex terminé."); } catch (exception e) {System.out.println ("indexerService.bulkindex e;" + e.getMessage ()); jeter e; }}}Faites attention à la méthode BulkIndex, qui est utilisée pour les données d'insertion par lots. Le volume est également la méthode des données d'insertion par lots officiellement recommandées par ES. Ici, le volume est inséré tous les 500 multiples entiers.
package com.tianyalei.ellasticsearch.Controller; import com.tianyalei.elasticsearch.model.person; import com.tianyalei.ellasticsearch.service.PersonService; import org.ellasticsearch.common.unit.distanceUnit; import org.ellasticsearch.index.query.geodIstanceQueryBuilder; import org.ellasticsearch.index.query.QueryBuilders; import org.ellasticsearch.search.sort.geodistancesOrtBuilder; import org.ellasticsearch.search.sort.sortbuilders; import org.ellasticsearch.search.sort.sortOrder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.pageRequest; import org.springframework.data.domain.pagable; import org.springframework.data.ellasticsearch.core.ElasticSearchTemplate; import org.springframework.data.elasticsearch.core.query.NativesEarchQueryBuilder; import org.springframework.data.ellasticsearch.core.query.searchQuery; import org.springframework.web.bind.annotation.getMapping; import org.springframework.web.bind.annotation.restController; import java.text.decimalformat; import java.util.arraylist; Importer java.util.list; import java.util.random; @RestController public class PersonController {@Autowired PersonService PersonService; @Autowired elasticsearchTemplate elasticsearchTemplate; @GetMapping ("/ add") Objet public Add () {double lat = 39.929986; Double Lon = 116,395645; List <onon> PersonList = new ArrayList <> (900000); pour (int i = 100000; i <1000000; i ++) {double max = 0,00001; double min = 0,000001; Aléatoire aléatoire = nouveau aléatoire (); double s = random.nextDouble ()% (max - min + 1) + max; DECIMALFORMAT DF = NOUVEAU DECIMALFORMAT ("###### 0.000000"); // System.out.println (s); String lons = df.format (s + lon); Chaîne lats = df.format (s + lat); Double dlon = double.valueof (lons); Double dlat = double.valueof (lats); Personne personne = new personne (); personne.setid (i); personne.setName ("name" + i); personne.setphone ("tel" + i); personne.setAddress (dlat + "," + dlon); PersonList.add (personne); } PersonService.BulkIndex (PersonList); // SearchQuery SearchQuery = new NativesearchQueryBuIlder (). WithQuery (QueryBuilders.QuerystringQuery ("Spring Boot or Book")). Build (); // Liste <Reart> Articles = Elas, TICSEARCHTEmplate.Queryforlist (SE, Archquery, Article.class); // pour (Article Article: Articles) {// System.out.println (article.ToString ()); //} return "Ajouter des données"; } / ** * GEO_DISTANCE: Trouvez l'emplacement dans une certaine plage d'un certain point central GEO_BOUNDING_BOX: Trouvez l'emplacement dans une zone rectangulaire GEO_DISTANCE_RANGE: Trouvez l'emplacement entre Min et Max Geo_Polygon: Trouvez l'emplacement dans un polygone. Le tri peut être utilisé pour trier * / @getMapping ("/ Query") Public Object Query () {double lat = 39.929986; Double Lon = 116,395645; Long NowTime = System.CurrentTimemillis (); // interroge dans une certaine latitude et longitude à moins de 100 mètres. GeoDistanceQueryBuilder Builder = QueryBuilders.GeoDistanceQuery ("Adresse"). Point (Lat, Lon) .Distance (100, DistanceUnit.Meters); GeoDistancesOrtBuilder sortBuilder = sortBuilders.GeoDistancesOrt ("Address") .point (lat, lon) .unit (DistanceUnit.Meters) .Order (SORTORDEDR.ASC); Pagable Pagable = New PageRequest (0, 50); NativesearchQueryBuIlder Builder1 = new NativesearchQueryBuilder (). Avec Filter (Builder) .WithSort (SortBuilder) .WithPagable (Pagable); SearchQuery searchQuery = builder1.build (); // QueryForList est paginée par défaut et le questionnaire QueryForpage est utilisé. La valeur par défaut est 10 LIST <Son PersonList = elasticsearchTemplate.Queryforlist (SearchQuery, Person.class); System.out.println ("TimeConsuming:" + (System.Currenttimemillis () - NowTime)); retour de la liste de personnes; }} En regardant la classe du contrôleur, dans la méthode ADD, nous insérons 900 000 données de test et générons des adresses de latitude et de longitude différentes au hasard.
Dans la méthode de requête, nous construisons une condition de requête à moins de 100 mètres de la requête, triée selon la distance et paginant 50 éléments par page. Si Pagable n'est pas spécifié, la question de questionnalité d'Estemplate est 10 par défaut, ce qui peut être vu via le code source.
Démarrez le projet, exécutez d'abord Ajouter et attendez que des millions de données soient insérées, pendant environ quelques dizaines de secondes.
Exécutez ensuite la requête et voyez les résultats.
La première requête a pris plus de 300 ms, et le temps a chuté considérablement après la requête à environ 30 ms, car ES a été automatiquement mis en mémoire.
On peut voir que ES complète très rapidement la requête de l'emplacement géographique. Convient aux requêtes telles que les personnes voisines et les requêtes de portée.
PostScript: Dans une utilisation ultérieure, dans la version 2.3 Elasticsearch, le géotype ne peut pas être indexé en fonction de la méthode d'écriture ci-dessus. L'entrée ES est une chaîne au lieu du géofile marqué. Voici un enregistrement de la solution, modifiez le type de chaîne à GeoPoint, et il est emballé sous org.springframework.data.elasticsearch.core.geo.geopoint. Ensuite, vous devez appeler explicitement la méthode de mappage lors de la création de l'index pour mapper correctement sur GeoField.
comme suit
if (! elasticsearchTemplate.Indexexists ("ABC")) {elasticsearchTemplate.createIndex ("ABC"); elasticsearchTemplate.putmapping (personne.class); }Ce qui précède est tout le contenu de cet article. J'espère que cela sera utile à l'apprentissage de tous et j'espère que tout le monde soutiendra davantage Wulin.com.