Artikel sebelumnya memperkenalkan bahwa Elasticsearch menggunakan repositori dan elasticsearchTemplate untuk membangun kondisi kueri yang kompleks, dan secara singkat memperkenalkan fungsi Elasticsearch untuk menggunakan lokasi geografis.
Dalam artikel ini, mari kita lihat fungsi menggunakan Elasticsearch untuk menyelesaikan permintaan data besar di dekat orang dan mencari data dalam kisaran N-meter.
Persiapkan lingkungan
Tes asli menggunakan Elasticsearch Versi 5.5.1, Springboot1.5.4, dan Spring-Data-Eelasticsearch2.4.
Buat proyek Springboot baru, periksa Elasticsearch dan Web.
File POM adalah sebagai berikut
<? 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 xsi: schemalocation = "http://maven.apache.org/pom/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <ModelVersion> </ModelVersion> <groupid> Com.Tianyale <ModelVersion> </ModelVersion> <groupdid> com.tificale <ModelVersion> </ModelVersion> <groupidid> Com.ticaCseale <ModelVersion> </ModelVersion> <groupidid> com.ticide <ModelVersion> </ModelVersion> <groupdid> com.tificale> <version> 0.0.1-Snapshot </version> <packaging> Jar </packaging> <name> Elasticsearch </name> <crickip> Proyek Demo untuk Spring Boot </creckripe> <partent> <groupid> org.springframework. <!-Pencarian Orangtua dari Repositori-> </induk> <properties> <proyity.build.sourceencoding> UTF-8 </project.build.sourceencoding> <poject.report.outputenCoding> UTF-8 </project.reporting.outputenceDing> <Java.8 </project.reporting.outputenCoding> <JaVa <Dependencies> <dependency> <GroupId> org.springframework.boot </groupid> <ArtifactId> Spring-boot-starter-data-elasticsearch </arttifactid> </gandendency> <Ruppendency> <Groupid> org. <dependency> <GroupId> org.springframework.boot </groupid> <ArtifactId> tes musim semi-boot-starter </t Artifactid> <scope> </seupope> </dependency> </Artidid> com.sun.jna </groupid> <Arttifactid> versi </art/art </dependencies> <build> <lugin> <lugin> <GroupId> org.springframework.boot </groupid> <ArTifactId> spring-boot-maven-plugin </t Artifactid> </lugin> </plugin> </bangun> </proyek>
Buat orang kelas model baru
paket com.tianyalei.elasticsearch.model; impor org.springframework.data.annotation.id; impor org.springframework.data.elasticsearch.annotations.document; impor org.springframework.data.elasticsearch.annotations.geopointfield; impor java.io.serializable; / *** Kelas model*/ @document (indexName = "elastic_search_project", type = "person", indexstoretype = "fs", shard = 5, replicas = 1, refreshInterval = "-1") Kelas publik mengimplementasikan serializable {@id private int id; nama string pribadi; telepon string pribadi; / ** * LATITAS LATITAS DAN LATIUDE * LATITUDE, LON LONDEUDE "40.715, -74.011" * Jika Anda menggunakan array, sebaliknya adalah benar [-73.983, 40.719] */ @geopointfield Alamat string pribadi; publik int getId () {return id; } public void setid (int id) {this.id = id; } public string getName () {return name; } public void setName (name string) {this.name = name; } public string getPhone () {return phone; } public void setPhone (string phone) {this.phone = phone; } public String getAddress () {alamat kembali; } public void setAddress (Alamat String) {this.address = alamat; }} Saya menggunakan bidang alamat untuk mewakili posisi garis lintang dan bujur. Perhatikan bahwa menggunakan string [] dan string berbeda ketika menunjukkan garis lintang dan bujur, lihat komentar.
impor com.tianyalei.elasticsearch.model.person; impor org.springframework.data.elasticsearch.repository.elasticsearchrepository; Antarmuka Publik PersonRepository Memperluas ElasticsearchRepository <Person, Integer> {} Lihatlah kelas layanan dan selesaikan fungsi memasukkan data uji. Saya menempatkan fungsi kueri di pengontrol. Demi kenyamanan, itu harus ditempatkan dalam layanan secara normal.
paket com.tianyalei.elasticsearch.service; impor com.tianyalei.elasticsearch.model.person; impor com.tianyalei.elasticsearch.repository.personRepository; impor org.springframework.beans.factory.annotation.Autowired; impor org.springframework.data.elasticsearch.core.elasticsearchTemplate; impor org.springframework.data.elasticsearch.core.query.indexQuery; impor org.springframework.stereotype.service; impor java.util.arraylist; impor java.util.list; @Service Public Class Personservice {@Autowired PersonRepository PersonRepository; @Autowired ElasticsearchTemplate ElasticsearchTemplate; Private Static Final String person_index_name = "elastic_search_project"; Private Static Final String Person_index_Type = "orang"; orang publik menambahkan (orang orang) {return personrepository.save (orang); } public void bulkIndex (Daftar <Fon> personList) {int counter = 0; coba {if (! ElasticsearchTemplate.Indexexists (person_index_name)) {ElasticSearchTemplate.createIndex (person_index_type); } Daftar <Peresakan Queries = ArrayList baru <> (); untuk (orang orang: orang) {indexQuery indexQuery = new indexQuery (); indexQuery.setId (person.getId () + ""); indexQuery.setObject (orang); indexQuery.setIndexName (person_index_name); indexQuery.settype (person_index_type); // Langkah -langkah di atas juga dapat digunakan untuk membangun menggunakan indexQueryBuilder // indexQuery index = new IndexQueryBuilder (). Withid (person.getId () + "") .withObject (orang) .build (); kueries.add (indexQuery); if (counter % 500 == 0) {ElasticsearchTemplate.bulkindex (kueri); kueri.clear (); System.out.println ("BulkIndex Counter:" + Counter); } counter ++; } if (queries.size ()> 0) {ElasticsearchTemplate.bulkindex (kueri); } System.out.println ("BulkIndex selesai."); } catch (Exception e) {System.out.println ("Indexerservice.BulkIndex e;" + e.getMessage ()); lempar e; }}}Perhatikan metode BulkIndex, yang digunakan untuk batch memasukkan data. Bulk juga merupakan metode data insert batch yang secara resmi direkomendasikan oleh ES. Di sini, curah dimasukkan setiap 500 kelipatan integer.
paket com.tianyalei.elasticsearch.controller; impor com.tianyalei.elasticsearch.model.person; impor com.tianyalei.elasticsearch.service.personservice; impor org.elasticsearch.common.unit.distanceunit; impor org.elasticsearch.index.query.geodistanceQueryBuilder; impor org.elasticsearch.index.query.querybuilders; impor org.elasticsearch.search.sort.geodistancesortbuilder; impor org.elasticsearch.search.sort.sortbuilders; impor org.elasticsearch.search.sort.sortorder; impor org.springframework.beans.factory.annotation.Autowired; impor org.springframework.data.domain.pagerequest; impor org.springframework.data.domain.pageable; impor org.springframework.data.elasticsearch.core.elasticsearchTemplate; impor org.springframework.data.elasticsearch.core.query.nativeSearchQueryBuilder; impor org.springframework.data.elasticsearch.core.query.searchQuery; impor org.springframework.web.bind.annotation.getmapping; impor org.springframework.web.bind.annotation.RestController; impor java.text.decimalformat; impor java.util.arraylist; impor java.util.list; impor java.util.random; @RestController Public Class PersonController {@Autowired Personservice Personservice; @Autowired ElasticsearchTemplate ElasticsearchTemplate; @GetMapping ("/add") Objek Publik Tambah () {Double Lat = 39.929986; Lon ganda = 116.395645; Daftar <Son> personList = new ArrayList <> (900000); untuk (int i = 100000; i <1000000; i ++) {double max = 0,00001; min ganda = 0,000001; Acak acak = acak baru (); double s = random.nextdouble () % (maks - min + 1) + maks; Decimalformat df = decimalformat baru ("###### 0.000000"); // System.out.println (s); String lons = df.format (s + lon); String lats = df.format (s + lat); Double dlon = double.valueof (lons); DLAT ganda = double.valueof (lats); Orang orang = orang baru (); orang.setid (i); person.setname ("name" + i); orang.setphone ("tel" + i); person.setAddress (dlat + "," + dlon); personlist.add (orang); } Personservice.bulkindex (personlist); // SearchQuery SearchQuery = NEW NATIVECHQUYYBUILDER (). WithQuery (QueryBuilders.QueryStringQuery ("Spring Boot atau Book")). Build (); // Daftar <TARTERT> Artikel = ELAS, TicsearchTemplate.QueryForList (SE, Archquery, Article.class); // untuk (artikel artikel: artikel) {// system.out.println (artikel.toString ()); //} return "Tambahkan data"; } /*** geo_distance: Temukan lokasi dalam kisaran tertentu dari titik tengah tertentu geo_bounding_box: temukan lokasi dalam area persegi panjang geo_distance_range: temukan lokasi antara min dan max geo_polygon: temukan lokasi dalam poligon. Sortir dapat digunakan untuk mengurutkan */ @getmapping ("/ kueri") kueri objek publik () {double lat = 39.929986; Lon ganda = 116.395645; Long nowtime = system.currentTimemillis (); // Permintaan dalam garis lintang dan bujur tertentu dalam jarak 100 meter. Geodistancequerybuilder builder = querybuilders.geodistanceQuery ("alamat"). Point (lat, lon) .distance (100, DistanceUnit.meters); Geodistancesortbuilder sortbuilder = sortbuilders.geodistancesort ("alamat") .point (lat, lon) .unit (DistanceUnit.meters) .order (sortorder.asc); Pagable pagable = pagerequest baru (0, 50); NativeSearchQueryBuilder builder1 = new new nativeCareQueryBuilder (). Withfilter (builder) .withsort (sortbuilder) .withpageable (pagable); SearchQuery SearchQuery = builder1.build (); // QueryForList diserahkan secara default, dan queryforpage digunakan. Defaultnya adalah 10 Daftar <Fon> personList = ElasticsearchTemplate.QueryForList (SearchQuery, Person.class); System.out.println ("TimeConsuming:" + (System.CurrentTimeMillis () - Nowtime)); daftar orang yang kembali; }} Melihat kelas pengontrol, dalam metode ADD, kami memasukkan 900.000 data uji dan secara acak menghasilkan alamat lintang dan bujur yang berbeda.
Dalam metode kueri, kami membangun kondisi kueri yang berada dalam jarak 100 meter dari kueri, diurutkan sesuai jarak, dan paging 50 item per halaman. Jika di sampel tidak ditentukan, QueryForlist of Estemplate adalah 10 secara default, yang dapat dilihat melalui kode sumber.
Mulai proyek, jalankan Tambahkan terlebih dahulu, dan tunggu jutaan data dimasukkan, selama sekitar beberapa lusin detik.
Kemudian jalankan kueri dan lihat hasilnya.
Kueri pertama membutuhkan lebih dari 300 ms, dan waktu turun secara signifikan setelah kueri lagi, menjadi sekitar 30 ms, karena ES telah secara otomatis di -cache ke memori.
Dapat dilihat bahwa ES menyelesaikan permintaan lokasi geografis dengan sangat cepat. Cocok untuk kueri seperti orang di dekatnya dan kueri Lingkup.
Postscript: Dalam penggunaan nanti, dalam Elasticsearch versi 2.3, geotipe tidak dapat diindeks sesuai dengan metode penulisan di atas. Entri ES adalah string, bukan geofil yang ditandai. Berikut adalah catatan solusi, memodifikasi tipe string menjadi geopoint, dan dikemas di bawah org.springframework.data.elasticsearch.core.geo.geopoint. Maka Anda perlu secara eksplisit memanggil metode pemetaan saat membuat indeks untuk memetakan dengan benar ke Geofield.
sebagai berikut
if (! ElasticsearchTemplate.Indexexists ("ABC")) {ElasticsearchTemplate.CreateIndex ("ABC"); ElasticsearchTemplate.putMapping (person.class); }Di atas adalah semua konten artikel ini. Saya berharap ini akan membantu untuk pembelajaran semua orang dan saya harap semua orang akan lebih mendukung wulin.com.