В предыдущей статье представилась, что Elasticsearch использует репозиторий и ElasticsearchTemplate для создания сложных условий запроса и кратко вводит функцию Elasticsearch для использования географического положения.
В этой статье давайте посмотрим на функцию использования Elasticsearch для завершения большого запроса данных поблизости и поиск данных в диапазоне N-метров.
Подготовьте окружающую среду
Настоящий тест использует последнюю версию Elasticsearch 5.5.1, Springboot1.5.4 и Spring-Data-Elasticsearch2.1.4.
Создайте новый проект Springboot, проверьте Elasticsearch и Web.
Файл POM выглядит следующим образом
<? 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"> <dolidayversion> 4.0.0 </modelversion> <groupid> com.tianyalei </GroupId> <TratifactIds> <TratifactIds> <TratifActIds> <TratifactIds> <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/> <!-Поиск родителя от репозитория-> </parent> <properties> <project.build.sourceencoding> utf-8 </project.build.sourceEncoding> <project.Report.OutputEncoding> utf-8 </project.Reporting.outputencing> <java.version> 1,8 </project.Verting <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 </GroupId> <artifactid> spring-boot-starter-test </artifactid> <crappope> test </scope> </depervice> <dehydency> <groupid> com.sun.jna </GroupD> <strifactid> jna </artifactid> <service> 3.0. <blicins> <blicin> <groupid> org.springframework.boot </GroupId> <strifactid> Spring-boot-maven-plugin </artifactid> </plugin> </plugins> </build> </project>
Создать нового модельного класса
пакет com.tianyalei.elasticsearch.model; Импорт org.springframework.data.annotation.id; Импорт org.springframework.data.elasticsearch.annotations.document; Импорт org.springframework.data.elasticsearch.annotations.geopointfield; импортировать java.io.serializable; / *** Класс модели*/ @document (indexname = "elastic_search_project", type = "person", indexstoreType = "fs", shards = 5, replicas = 1, rebreshInterval = "-1") общедоступный класс. Личность реализует сериализируемый {@Id private ID; Приватное название строки; Частный строковый телефон; / ** * Географическое местоположение широта и долгота * широта, Lon Londitude "40.715, -74.011" * Если вы используете массив, противоположность верна [-73.983, 40.719] */ @geopointfield Частный строковый адрес; 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 Phone; } public void SetPhone (String Phone) {this.phone = phone; } public String getAddress () {return Adder; } public void setAddress (строковый адрес) {this.address = address; }} Я использую поле адреса для представления позиции широты и долготы. Обратите внимание, что использование string [] и string отличается при обозначении широты и долготы, см. Комментарии.
Импорт com.tianyalei.elasticsearch.model.person; Import org.springframework.data.elasticsearch.repository.elasticsearchRepository; Public Interface PersonRepository расширяет ElasticSearchRepository <Person, Integer> {} Посмотрите на класс службы и выполните функцию вставки тестовых данных. Я поместил функцию запроса в контроллер. Ради удобства, это должно быть оказано в обслуживании нормально.
пакет com.tianyalei.elasticsearch.service; Импорт com.tianyalei.elasticsearch.model.person; Импорт com.tianyalei.elasticsearch.repository.personRepository; Импорт org.springframework.beans.factory.annotation.autowired; Import org.springframework.data.elasticsearch.core.elasticsearchTemplate; Import org.springframework.data.elasticsearch.core.query.indexquery; Импорт org.springframework.stereotype.service; импортировать java.util.arraylist; импортировать java.util.list; @Service public class personservice {@autowired PersonRepository PersonRepository; @Autowired elasticsearchtemplate elasticsearchtemplate; Приватная статическая конечная строка Person_index_name = "Elastic_search_project"; частная статическая конечная строка Person_index_type = "person"; публичное лицо добавить (лицо) {return personRepository.save (person); } public void bulkindex (список <person> personlist) {int counter = 0; попробуйте {if (! elasticsearchTemplate.indexexists (person_index_name)) {elasticsearchTemplate.createDex (person_index_type); } List <dudexquery> Queries = new ArrayList <> (); для (Person Person: PersonList) {indexquery indexQuery = new IndexQuery (); indexQuery.SetId (person.getId () + ""); indexQuery.SetObject (человек); indexQuery.SetIndExname (Person_Index_Name); indexQuery.SetType (person_Index_type); // Приведенные выше шаги также могут использоваться для построения с использованием indexquerybuilder // indexquery index = new IndexQueryBuilder (). WithId (person.getId () + "") .withobject (человек) .build (); Queries.add (indexquery); if (счетчик % 500 == 0) {elasticsearchtemplate.bulkindex (запросы); Queries.clear (); System.out.println ("Счетчик Bulkindex:" + счетчик); } counter ++; } if (queries.size ()> 0) {elasticsearchTemplate.bulkindex (Queries); } System.out.println ("Bulkindex завершен."); } catch (Exception e) {System.out.println ("indexerService.bulkindex e;" + e.getMessage ()); бросить E; }}}Обратите внимание на метод Bulkindex, который используется для падения данных. Настройка также является методом пакетной вставки данных, официально рекомендованных ES. Здесь объем вводится каждые 500 целочисленных множества.
пакет com.tianyalei.elasticsearch.controller; Импорт com.tianyalei.elasticsearch.model.person; Импорт com.tianyalei.elasticsearch.service.personservice; Импорт org.elasticsearch.common.unit.distanceUnit; Import org.elasticsearch.index.query.geodistanceQueryBuilder; Импорт org.elasticsearch.index.query.querybuilders; Import org.elasticsearch.search.sort.geodistancesortbuilder; Import org.elasticsearch.search.sort.sortbuilders; Import org.elasticsearch.search.sort.sortorder; Импорт org.springframework.beans.factory.annotation.autowired; импорт org.springframework.data.domain.pagerequest; Импорт org.springframework.data.domain.pagable; Import org.springframework.data.elasticsearch.core.elasticsearchTemplate; Import org.springframework.data.elasticsearch.core.query.nativeSearchQueryBuilder; Import org.springframework.data.elasticsearch.core.query.searchquery; Импорт org.springframework.web.bind.annotation.getMaping; Импорт org.springframework.web.bind.annotation.restcontroller; импортировать java.text.decimalformat; импортировать java.util.arraylist; импортировать java.util.list; импортировать java.util.random; @Restcontroller public class personcontroller {@autowired personservice personservice; @Autowired elasticsearchtemplate elasticsearchtemplate; @Getmapping ("/add") public object add () {double lat = 39.929986; Double LON = 116,395645; Список <Derson> PersonList = new ArrayList <> (900000); для (int i = 100000; i <1000000; i ++) {Double max = 0,00001; двойной мин = 0,000001; Случайный случайный = new Random (); double s = random.nextdouble () % (max - min + 1) + max; Decimalformat df = new DecimalFormat ("###### 0,000000"); // 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.setid (i); person.setname ("имя" + i); person.setphone ("tel" + i); Person.setAddress (dlat + "," + dlon); PersonList.Add (человек); } personservice.bulkindex (PersonList); // searchquery searchquery = new ContivenSearchQueryBuilder (). WithQuery (QueryBuilders.QueryStringQuery ("Spring Boot или Book")). Build (); // Список <статья> статьи = elas, ticsearchtemplate.queryforlist (se, archquery, article.class); // для (статья статьи: статьи) {// system.out.println (article.tostring ()); //} return "добавить данные"; } /*** GEO_DISTANCE: Найдите местоположение в определенном диапазоне определенной центральной точки GEO_BOUNDING_BOX: Найдите местоположение в области прямоугольника GEO_DISTANCE_RANGE: Найдите местоположение между MIN и MAX GEO_POLYGON: Найдите место в полигоне. Сортировка может использоваться для сортировки */ @getmapping ("/ Query") public Object Query () {double lat = 39.929986; Double LON = 116,395645; Long nowtime = system.currenttimemillis (); // Запрос в пределах определенной широты и долготы в пределах 100 метров. GeoDistancequeryBuilder Builder = QueryBuilders.GeoDistanceQuery («адрес»). Point (LAT, LON). Дистанция (100, DistanceUnit.Memers); GeoDistancesortBuilder SortBuilder = SortBuilders.GeoDistancesort ("адрес") .point (lat, LON) .Unit (DivandUnit.Memers) .Order (sortOrder.ASC); Пегсный слойный = новый PageRequest (0, 50); ContivensearchQueryBuilder Builder1 = New ContivesSearchQueryBuilder (). WithFilter (Builder). WithSort (SortBuilder) .WithBagable (Pagable); Searchquery searchquery = builder1.build (); // QueryForList по умолчанию высоко оценивается, и используется QueryForpage. По умолчанию 10 List <Personse> PersonList = ElasticSearchTemplate.QueryForlist (SearchQuery, Person.Class); System.out.println ("TimeConsuming:" + (System.currentTimeMillis () - сейчас время)); вернуть личность; }} Глядя на класс контроллера, в методе добавления мы вставляем 900 000 тестовых данных и случайным образом генерируем различные адреса широты и долготы.
В методе запроса мы строим условие запроса, которое находится в пределах 100 метров от запроса, отсортировано в соответствии с расстоянием и подтягивающимся 50 пунктами на страницу. Если не указан переночный, то Queryforlist of Estemplate по умолчанию составляет 10, что можно увидеть через исходный код.
Начните проект, выполните сначала добавить и дождитесь вставки миллионов данных, в течение нескольких десятков секунд.
Затем выполните запрос и увидите результаты.
Первый запрос занял более 300 мс, и время значительно сократилось после запроса, примерно до 30 мс, потому что ES автоматически кэшировал в памяти.
Видно, что ES очень быстро завершает запрос географического положения. Подходит для запросов, таких как близлежащие люди и запрос на область применения.
PostScript: в последующем использовании, в версии elasticsearch версии 2.3, геотип не может быть проиндексирован в соответствии с вышеуказанным методом записи. Запись ES является строкой вместо отмеченной геофильки. Вот запись решения, измените тип строки на GeoPoint, и он упакован в org.springframework.data.elasticsearch.core.geo.geopoint. Затем вам нужно явно вызовать метод отображения при создании индекса для правильной карты в Geofield.
следующее
if (! ElasticSearchTemplate.indexexists ("abc")) {elasticSearchTemplate.createIndex ("abc"); ElasticsearchTemplate.putmapping (Person.class); }Выше всего содержание этой статьи. Я надеюсь, что это будет полезно для каждого обучения, и я надеюсь, что все будут поддерживать Wulin.com больше.