Der vorherige Artikel führte vor, dass Elasticsearch Repository und ElasticsearchTemplate verwendet, um komplexe Abfragebedingungen zu erstellen, und die Funktion von Elasticsearch kurz vorstellt, um den geografischen Standort zu verwenden.
Schauen wir uns in diesem Artikel die Funktion der Verwendung von Elasticsearch an, um die großen Datenabfrage in der Nähe von Personen in der Nähe zu vervollständigen und nach Daten innerhalb des N-Meter-Bereichs zu suchen.
Die Umgebung vorbereiten
Der native Test verwendet die neueste Elasticsearch-Version 5.5.1, SpringBoot1.5.4 und Spring-Data-E-E-E-E-E-E-E-E-E-E-E-E-E-E-E-E-E-E-E-E-E-E-E-E-E-E-E-E-E-E-E-ERASTICSECH2.1.4.
Erstellen Sie ein neues Springboot -Projekt, überprüfen Sie Elasticsearch und Web.
Die POM -Datei lautet wie folgt
<? XSI: Schemalocation = "http://maven.apache.org/pom/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion> 4.0.0 </modelversion> </arthactiAntIntIntIf.> </GroupIntIntIfly> </GroupIntIntIfly> </GroupIntIntIfly> </Groupid> </artifactid> </artifactid> </artifactid> </artifactid> </artifactid> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>elasticsearch</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.4.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <Depelencies> <Depopentcy> <gruppe> org.springFramework.boot </GroupId> <artifactId> Spring-Boot-Starter-Data-Elasticsearch </artifactID> </abhängig> <Depopy <Depepecy> <GroupId> org.springFramework.boot </GroupId> <artifactId> Spring-Boot-Starter-Test </artifactId> <Schops> test </scope> </abhängig> <Depopenty> <gruppeId> com.sun.jna </GroupID> <artifactid> jna </artifactid> </artifactid> </artifactid> </artifactid> </artifactid> </artifactid> </artifactid> </artifactid> </abhängigen> <build> <plugins> <plugin> <gruppe> org.springFramework
Erstellen Sie eine neue Modellklassenperson
Paket com.tianyalei.elasticsearch.model; import org.springframework.data.annotation.id; import org.springframework.data.Elasticsearch.annotations.document; import org.springframework.data.elasticsearch.annotations.geOpointfield; importieren java.io.serializable; / *** Modellklasse*/ @document (indexname = "elastic_search_project", type = "person", indexstoretype = "fs", shards = 5, replicas = 1, RefreshInterval = "-1") öffentliche Klasse Person implementiert serialisierbare {@ID private int id; privater Zeichenfolge Name; privates String -Telefon; / ** * Geografischer Ort Breite und Längengrad * Breitengrad, Longitude "40.715, -74.011" * Wenn Sie ein Array verwenden, ist das Gegenteil wahr [-73.983, 40.719] */ @Geopointfield Private String-Adresse; public int getid () {return id; } public void setId (int id) {this.id = id; } public String getName () {return name; } public void setName (String -Name) {this.name = name; } public String getphone () {return telefon; } public void setPhone (String -Telefon) {this.phone = Telefon; } public String getAddress () {Rückgabeadresse; } public void setAddress (String -Adresse) {this.address = address; }} Ich benutze das Adressfeld, um die Position des Breitengrads und der Länge darzustellen. Beachten Sie, dass die Verwendung von String [] und String bei der Bezeichnung von Breitengrad und Längengrad unterscheiden, siehe Kommentare.
import com.tianyalei.elasticsearch.model.person; import org.springframework.data.elasticsearch.repository.elasticsearchrepository; öffentliche Schnittstelle PersonRepository erweitert ElasticsearchRepository <Person, Integer> {} Schauen Sie sich den Serviceunterricht an und vervollständigen Sie die Funktion des Einfügens von Testdaten. Ich stelle die Abfragefunktion in den Controller. Aus Gründen der Bequemlichkeit sollte es normal in den Service platziert werden.
Paket com.tianyalei.elasticsarch.service; import com.tianyalei.elasticsearch.model.person; import com.tianyalei.elasticsearch.repository.personrepository; import org.springframework.beans.factory.annotation.autowired; import org.springframework.data.Elasticsearch.core.ElasticsearchTemplate; import org.springframework.data.elasticsearch.core.query.indexquery; import org.springframework.stereotype.service; Import Java.util.ArrayList; importieren java.util.list; @Service Public Class personSservice {@autowired personRepository PersonRepository; @Autowired ElasticSearchTemplate ElasticSearchTemplate; private statische endgültige String person_index_name = "elastic_search_project"; private statische endgültige String person_index_type = "Person"; öffentliche Person add (Person Person) {return personRepository.save (Person); } public void bulkIndex (Liste <Person> Personlist) {int counter = 0; try {if (! ElasticSearchTemplate.Indexists (person_index_name)) {ElasticSearchTemplate.createinNex (person_index_type); } List <IndexQuery> queries = new ArrayList <> (); für (Person Person: Personlist) {indexQuery indexQuery = new indexQuery (); indexQuery.setId (person.getId () + ""); IndexQuery.SetObject (Person); indexQuery.setIndexname (person_index_name); indexQuery.setType (person_index_type); // Die oben genannten Schritte können auch verwendet werden, um mit IndexQueryBuilder // IndexQuery index = new indexQueryBuilder () zu erstellen. WithId (person.getId () + ") .WithObject (Person) .build (); queries.add (IndexQuery); if (counter % 500 == 0) {ElasticSearchTemplate.bulkIndex (Abfragen); Abfragen.Clear (); System.out.println ("BulkIndex -Zähler:" + Zähler); } counter ++; } if (queries.size ()> 0) {ElasticSearchTemplate.bulkIndex (Abfragen); } System.out.println ("bulkIndex abgeschlossen."); } catch (Ausnahme e) {System.out.println ("IndexerService.bulkIndex e;" + e.getMessage ()); werfen e; }}}Achten Sie auf die BulkIndex -Methode, mit der Daten einfügen werden. Masse ist auch die Methode der von ES offiziell empfohlenen Stapeldaten. Hier wird alle 500 Ganzzahl -Vielfachen eingefügt.
Paket com.tianyalei.elasticsearch.controller; import com.tianyalei.elasticsearch.model.person; import com.tianyalei.elasticsearch.service.personservice; import org.elasticsearch.common.unit.distanceUnit; import org.elasticsearch.index.query.geodistanceQueryBuilder; import org.elasticsearch.index.query.querybuilders; import org.elasticsearch.search.sort.geodistancesortbuilder; import org.elasticsearch.search.sort.sortbuilders; import org.elasticsearch.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.Elasticsearch.core.ElasticsearchTemplate; import org.springframework.data.elasticsearch.core.query.NeSearchQueryBuilder; import org.springframework.data.elasticsearch.core.query.searchQuery; import org.springframework.web.bind.annotation.getMapping; import org.springframework.web.bind.annotation.restController; importieren java.text.decimalformat; Import Java.util.ArrayList; importieren java.util.list; import Java.util.random; @RestController Public Class PersonController {@Autowired personSservice personSservice; @Autowired ElasticSearchTemplate ElasticSearchTemplate; @GetMapping ("/add") öffentliches Objekt add () {double lat = 39.929986; doppelte Lon = 116,395645; Liste <Person> personList = new ArrayList <> (900000); für (int i = 100000; i <1000000; i ++) {double max = 0,00001; doppelt min = 0,000001; Random random = new random (); double s = random.nextDouble () % (max - min + 1) + max; DecimalFormat df = new DecimalFormat ("####################»); // system.out.println (s); String lons = df.format (s + lon); String lats = df.format (s + lat); Double dlon = double.Valueof (lons); Double dlat = double.Valueof (lats); Person Person = New Person (); Person.Setid (i); Person.SetName ("Name" + i); Person.Setphone ("Tel" + i); Person.SetAddress (dlat + "," + dlon); Personlist.Add (Person); } PESTROService.bulkIndex (Personlist); // SearchQuery SearchQuery = New NativeSearchQueryBuilder (). WithQuery (querybuilders.queryStringQuery ("Spring Boot oder Book"). Build (); // List <Aktion> articles = elas, ticsearchTemplate.QueryForList (SE, ArchQuery, article.class); // für (Artikelartikel: Artikel) {// system.out.println (article.toString ()); //} return "Daten hinzufügen"; } /*** Geo_Distance: Finden Sie den Ort in einem bestimmten Bereich eines bestimmten Mittelpunkts Geo_Bounding_Box: Finden Sie den Standort innerhalb eines Rechteckbereichs Geo_Distance_Range: Finden Sie den Standort zwischen min und max geo_polygon: Finden Sie den Ort innerhalb eines Polygons. SORT kann verwendet werden, um */ @getmapping ("/ query") public Object query () {double lat = 39.929986; doppelte Lon = 116,395645; Lange heutzutage = System.currentTimemillis (); // Abfragen Sie innerhalb von 100 Metern innerhalb eines bestimmten Breitengrads und einer Länge. GeodistanceQueryBuilder Builder = Querybuilders.GeodistanceQuery ("Adresse"). Geodistancesortbuilder Sortbuilder = Sortbuilders.Geodistancesort ("Adresse"). Pageable lehbar = neuer pageRequest (0, 50); NativessearchQueryBuilder Builder1 = Neue NativeSearchQueryBuilder (). WithFilter (Builder) .WithSort (Sortbuilder). SearchQuery SearchQuery = builder1.build (); // QueryForList wird standardmäßig paginiert und die QueryForPage wird verwendet. Die Standardeinstellung ist 10 List <Person> Personlist = ElasticSearchTemplate.QueryForList (SearchQuery, Person.Class); System.out.println ("Zeitkonsum:" + (System.currentTimemillis () - jetzt Time)); Personlist zurückgeben; }} In der Controller -Klasse fügen wir in der Methode hinzufügen 900.000 Testdaten ein und generieren zufällig unterschiedliche Breiten- und Längengradadressen.
In der Abfragemethode erstellen wir eine Abfragebedingung, die sich innerhalb von 100 Metern von der Abfrage befindet, nach Entfernung sortiert und 50 Elemente pro Seite paget. Wenn nicht vorliegend angegeben wird, ist die Abfrageforlist von Estemplate standardmäßig 10, was über den Quellcode angezeigt werden kann.
Starten Sie das Projekt, führen Sie zuerst hinzufügen und warten Sie, bis Millionen von Daten einfügt werden, um etwa ein paar Dutzend Sekunden.
Führen Sie dann die Abfrage aus und sehen Sie die Ergebnisse.
Die erste Abfrage dauerte mehr als 300 ms, und die Zeit wurde nach der Anfrage nach der Anfrage erheblich gesunken, da ES automatisch in den Speicher gebracht wurde.
Es ist zu sehen, dass ES sehr schnell die Anfrage der geografischen Lage abgeschlossen hat. Geeignet für Fragen wie in der Nähe von Personen und Umfangsfragen.
PostScript: In späterer Verwendung kann der Geotyp in der Elasticsearch -Version 2.3 nicht gemäß der obigen Schreibmethode indiziert werden. Der ES -Eintrag ist anstelle des gekennzeichneten Geofiled. Hier ist ein Aufzeichnung der Lösung, ändern Sie den String -Typ auf GeoPoint und er ist unter org.springframework.data.Elasticsearch.core.geo.Geopoint verpackt. Anschließend müssen Sie die Zuordnungsmethode explizit aufrufen, wenn Sie den Index erstellen, um korrekt in Geofield zuzuordnen.
wie folgt
if (! ElasticSearchTemplate.Indexists ("ABC")) {ElasticSearchTemplate.CreateinNex ("ABC"); ElasticSearchTemplate.putMapping (Person.Class); }Das obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, es wird für das Lernen aller hilfreich sein und ich hoffe, jeder wird Wulin.com mehr unterstützen.