이전 기사는 Elasticsearch가 저장소 및 ElasticsearchTemplate를 사용하여 복잡한 쿼리 조건을 구축하고 Elasticsearch의 기능을 간단히 소개하여 지리적 위치를 사용한다고 소개했습니다.
이 기사에서는 Elasticsearch를 사용하여 근처의 대형 데이터 쿼리를 완료하고 N-Meter 범위 내에서 데이터를 검색하는 기능을 살펴 보겠습니다.
환경을 준비하십시오
기본 테스트는 최신 Elasticsearch 버전 5.5.1, SpringBoot1.5.4 및 Spring-Data-Elasticsearch2.1.4를 사용합니다.
새 SpringBoot 프로젝트를 작성하고 Elasticsearch 및 웹을 확인하십시오.
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.xsd"> <modeversion> 4.0.0 </modelversion> <groupid> com.tianyalei </groupsicid> artifactid> eritifactics> <버전> 0.0.1-snapshot </version> <packaging> jar </packaging> <name> elasticsearch </name> <description> 스프링 부츠를위한 데모 프로젝트 </descript> <perg.springframework.boot </groupid> <artifactid> spring-boot-starter-parent </artifactid> <version> </relate>>. 저장소에서 부모 조회-> </parent> <properties> <project.build.build.build.sourceencoding> utf-8 </project.build.sourceencoding> <project.reporting.outputencoding> utf-8 </project.reporting.outputencoding> <java.versition> 1.8 </java. <pectionency> <groupId> org.springframework.boot </groupid> <artifactid> 스프링-부트-스타터-데이터-엘라 스타 컬러 </artifactid> </dependency> <groupid> org.springframework.boot </groupid> <arepifactid> springboot-starter-web </artifactid> <groupid> org.springframework.boot </groupid> <artifactid> 스프링-부트 스타터-테스트 </artifactid> <cope> test </scope> </dependency> <prectionency> <groupId> com.sun.jna </groupid> <artifactid> jna </expence> 3.0.9 </version> 3.0.9 <플러그인> <플러그인> <groupid> org.springframework.boot </groupid> <artifactid> spring-boot-maven-plugin </artifactid> </plugin> </plugins> </build> </project>
새로운 모델 클래스 사람을 만듭니다
패키지 com.tianyalei.elasticsearch.model; import org.springframework.data.annotation.id; import org.springframework.data.elasticsearch.annotations.document; import org.springframework.data.elasticsearch.annotations.geopointfield; java.io.serializable import; / *** 모델 클래스*/ @document (indexname = "elastic_search_project", type = "person", indexStoreType = "fs", shards = 5, replicas = 1, refreshinterval = "-1") 공개 클래스 개인이 시리얼 리화 가능 {@id private ind; 개인 문자열 이름; 개인 문자열 전화; / ** * 지리적 위치 위도 및 경도 * 위도, lon longitude "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 (문자열 이름) {this.name = 이름; } public String getPhone () {반환 전화; } public void setphone (String Phone) {this.phone = 전화; } public String getAddress () {return address; } public void setAddress (문자열 주소) {this.address = 주소; }} 주소 필드를 사용하여 위도 및 경도 위치를 나타냅니다. 위도와 경도를 나타낼 때 String []와 String을 사용하면 주석을 참조하십시오.
com.tianyalei.elasticsearch.model.person import; org.springframework.data.elasticsearch.repository.elasticsearchRepository; Public Interface Personrepository Extends ElasticsearchRepository <Person, Integer> {} 서비스 클래스를 살펴보고 테스트 데이터 삽입 기능을 완료하십시오. 쿼리 기능을 컨트롤러에 넣었습니다. 편의를 위해 서비스에 정상적으로 배치해야합니다.
패키지 com.tianyalei.elasticsearch.service; com.tianyalei.elasticsearch.model.person import; com.tianyalei.elasticsearch.repository.personrepository import; org.springframework.beans.factory.annotation.autowired; org.springframework.data.elasticsearch.core.elasticsearchtemplate; org.springframework.data.elasticsearch.core.query.indexquery; org.springframework.stereotyp.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 (list <person> personlist) {int counter = 0; try {if (! elasticsearchtemplate.indexexists (person_index_name)) {elasticsearchtemplate.createIndex (person_index_type); } list <색인 Query> queries = new ArrayList <> (); for (person : personlist) {indexquery indexquery = new IndexQuery (); IndexQuery.setId (person.getId () + ""); IndexQuery.setObject (Person); IndexQuery.SetIndexName (person_index_name); IndexQuery.setType (person_index_type); // 위의 단계는 IndexQueryBuilder // IndexQuery Index = New IndexQueryBuilder (). withid (person.getId () + "") .witHobject (person) .build (); queries.add (indexQuery); if (coun queries.clear (); System.out.println ( "Bulkindex 카운터 :" + 카운터); } 카운터 ++; } if (queries.size ()> 0) {elasticsearchtemplate.bulkindex (queries); } system.out.println ( "BulkIndex가 완료되었습니다."); } catch (예외 e) {system.out.println ( "indexerservice.bulkindex e;" + e.getMessage ()); e 던지기; }}}삽입 데이터를 배치하는 데 사용되는 BulkIndex 방법에주의하십시오. Bulk는 또한 ES가 공식적으로 권장하는 배치 삽입 데이터 방법입니다. 여기에서 벌크는 500 개의 정수 배수마다 삽입됩니다.
패키지 com.tianyalei.elasticsearch.controller; com.tianyalei.elasticsearch.model.person import; com.tianyalei.elasticsearch.service.personservice import; 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; org.springframework.beans.factory.annotation.autowired; import org.springframework.data.domain.pagerequest; org.springframework.data.domain.pageable import; org.springframework.data.elasticsearch.core.elasticsearchtemplate; import org.springframework.data.elasticsearch.core.query.nativeSearchQueryBuilder; org.springframework.data.elasticsearch.core.query.searchQuery; org.springframework.web.bind.annotation.getMapping; org.springframework.web.bind.annotation.RestController; import java.text.decimalformat; java.util.arraylist 가져 오기; Java.util.list 가져 오기; java.util.random import; @RestController Public Class PersonController {@autowired personservice personservice; @autowired elasticsearchtemplate elasticsearchtemplate; @GetMapping ( "/add") public Object Add () {double lat = 39.929986; 더블 론 = 116.395645; List <person> personList = New ArrayList <> (900000); for (int i = 100000; i <10000000; i ++) {double max = 0.00001; 이중 최소 = 0.000001; 랜덤 random = new random (); double s = random.nextDouble () % (max -min + 1) + max; Decimalformat df = New Decimalformat ( "###### 0.000000"); // system.out.println (s); 문자열 lons = df.format (s + lon); 문자열 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 NativeSearchQueryBuilder (). // list <article> articles = elas, ticsearchtemplate.queryforList (SE, Archquery, article.class); // (기사 기사 : 기사) {// system.out.println (article.toString ()); //} return "데이터 추가"; } /*** GEO_DISTANCE : 특정 중심 지점의 특정 범위 내에서 위치를 찾으십시오 GEO_BANDING_BOX : 사각형 영역 내에서 위치를 찾으십시오 GEO_DISTANCE_RANGE : Min과 Max GEO_POLYGON 사이의 위치를 찾으십시오. 정렬을 사용하여 */ @getmapping ( "/ query") public object query () {double lat = 39.929986; 더블 론 = 116.395645; Long Nowtime = System.CurrentTimeMillis (); // 100 미터 이내에 특정 위도와 경도 내에서 쿼리. GeodistanceQueryBuilder Builder = QueryBuilders.geodistanceQuery ( "주소"). Point (Lat, Lon) .Distance (100, distionUnit.meters); geodistancesortBuilder SortBuilder = SortBuilders.geodistancesort ( "주소") .Point (lat, lon) .unit (distionUnit.meters) .Order (sortorder.asc); pagable pagable = 새로운 Pagerequest (0, 50); NATIVESEARCHQUERYBUILDER BUILDER1 = NEW NATIVESEARCHQUERYBUILDER (). SearchQuery SearchQuery = Builder1.Build (); // QueryForList는 기본적으로 Paginated이며 QueryForPage가 사용됩니다. 기본값은 10 목록 <personlist = elasticsearchtemplate.queryforList (searchQuery, person.class)입니다. System.out.println ( "TimeConsoring :" + (System.CurrentTimeMillis () -Nowtime)); 리턴 개인리스트; }} ADD 메소드에서 컨트롤러 클래스를 살펴보면 900,000 개의 테스트 데이터를 삽입하고 다른 위도 및 경도 주소를 무작위로 생성합니다.
쿼리 방법에서는 쿼리에서 100 미터 이내에있는 쿼리 조건을 구성하고 거리에 따라 정렬하고 페이지 당 50 개 항목을 페이징합니다. pagable이 지정되지 않은 경우, Estemplate의 쿼리 포리스트는 기본적으로 10이며 소스 코드를 통해 볼 수 있습니다.
프로젝트를 시작하고 먼저 추가를 실행하고 약 12 초 동안 수백만 개의 데이터를 삽입 할 때까지 기다립니다.
그런 다음 쿼리를 실행하고 결과를 확인하십시오.
첫 번째 쿼리는 300ms 이상이 걸렸고 쿼리 후 다시 시간이 약 30ms로 떨어졌습니다. ES는 자동으로 메모리로 캐시 되었기 때문입니다.
ES가 지리적 위치의 쿼리를 매우 빠르게 완료한다는 것을 알 수 있습니다. 인근 사람들 및 스코프 쿼리와 같은 쿼리에 적합합니다.
PostScript : 나중에 사용하면 Elasticsearch 버전 2.3에서 위의 쓰기 방법에 따라 지리색을 색인화 할 수 없습니다. ES 항목은 표시된 지오 필드 대신 문자열입니다. 다음은 솔루션의 레코드입니다. 문자열 유형을 Geopoint로 수정하고 org.springframework.data.elasticsearch.core.geo.geopoint 아래에 포장됩니다. 그런 다음 지오 필드에 올바르게 맵핑하기 위해 인덱스를 작성할 때 매핑 방법을 명시 적으로 호출해야합니다.
다음과 같이
if (! elasticsearchtemplate.indexExists ( "abc")) {elasticsearchtemplate.createIndex ( "abc"); ElasticsearchTemplate.putMapping (person.class); }위는이 기사의 모든 내용입니다. 모든 사람의 학습에 도움이되기를 바랍니다. 모든 사람이 wulin.com을 더 지원하기를 바랍니다.