前の記事では、ElasticSearchがリポジトリとElasticsearchTemplateを使用して複雑なクエリ条件を構築し、ElasticSearchの機能を簡単に紹介して地理的位置を使用することを紹介しました。
この記事では、ElasticSearchを使用して近くの大規模なデータを完成させ、N-Meter範囲内のデータを検索する機能を見てみましょう。
環境を準備します
ネイティブテストでは、最新のElasticSearchバージョン5.5.1、Springboot1.5.4、およびSpring-Data-Elasticsearch2.1.4を使用しています。
新しいスプリングブートプロジェクトを作成し、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 <http://www.w3.org/2001 xsi:schemalocation = "http://maven.apache.org/pom/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.0.sdsd"> <modelversion> 4.0.0 </modelversion> <グループ<グループ</groupid> <artifactId>elasticsearch</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> <バージョン> 1.5.4.Release </version> <RecationPath/> <! - リポジトリからのlookup parent-> </parent> <properties> <propert.build.sourceencoding> utf-8 </project.build.sourceEncoding> <project.reporting.outputencoding <java.version> 1.8 </java.version> </properties> <dependencies> <dependency> groupid> org.springframework.boot </groupid> <artifactid> spring-boot-starter-data-elasticsearch </artifactid> </dentency> <artifactid> spring-boot-starter-web </artifactid> </dependency> <dependency> groupid> org.springframework.boot </groupid> <artifactid> spring-boot-starter-test </artifactid> <scope> test </scope> </dependency> <deprogency> <groupid> <groupid> <groupid> <groupid> <groupid> <groupId> <groupId> <artifactid> jna </artifactid> <バージョン> 3.0.9 </version> </dependency> </dependencies> <bultins> <blubins> <groupid> org.springframework.boot </groupid> <artifactid> spring-boot-maven-plugin </artifactid> </plugin> </plugin
新しいモデルクラスの人を作成します
パッケージcom.tianyalei.elasticsearch.model; Import org.springframework.data.annotation.id; org.springframework.data.elasticsearch.annotations.documentをインポートします。 Import org.springframework.data.elasticsearch.annotations.geopointfield; java.io.serializableをインポートします。 / ** Model class*/ @document(indexname = "Elastic_search_project"、type = "person"、indexstoretype = "fs"、shards = 5、replicas = 1、lephicas = 1、lefficienterval = "-1")パブリッククラスの人はシリアル化可能{@id private int id;プライベート文字列名;プライベート文字列電話; / ** *地理的位置緯度と経度 *緯度、LON経度 "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 Address; } public void setAddress(stringアドレス){this.address = address; }}アドレスフィールドを使用して、緯度と経度の位置を表します。文字列[]と文字列を使用すると、緯度と経度を示す場合は異なることに注意してください。コメントを参照してください。
com.tianyalei.elasticsearch.model.personをインポートします。 intorg.springframework.data.elasticsearch.repository.elasticsearchrepository;パブリックインターフェイスPersonRepositoryはElasticsearchRepository <人、integer> {}を拡張しますサービスクラスを見て、テストデータの挿入機能を完了します。クエリ機能をコントローラーに配置します。便利なため、通常はサービスに配置する必要があります。
パッケージcom.tianyalei.elasticsearch.service; com.tianyalei.elasticsearch.model.personをインポートします。 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; org.springframework.stereotype.serviceをインポートします。 java.util.arraylistをインポートします。 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 = "person";パブリックパーソン(パーソン){personeRepository.save(person); } public void bulkindex(list <person> personlist){int counter = 0; try {if(!elasticsearchtemplate.indexists(person_index_name)){elasticsearchtemplate.createindex(person_index_type); } list <IndexQuery> queries = new ArrayList <>(); for(person 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()。 queries.add(indexquery); if(counter%500 == 0){elasticsearchtemplate.bulkindex(queries); queries.clear(); system.out.println( "bulkindex counter:" + counter); } 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をインポートします。 Import org.elasticsearch.common.unit.distanceUnit; Import org.elasticsearch.index.query.geodistancequerybuilder; Import org.elasticsearch.index.query.querybuilders; org.elasticsearch.search.sort.geodistancesortbuilderをインポートします。 Import org.elasticsearch.search.sort.sortbuilders; import org.elasticsearch.search.sort.sortorder; Import org.springframework.beans.factory.annotation.autowired; org.springframework.data.domain.pagerequestをインポートします。 Import org.springframework.data.domain.pageable; Import org.springframework.data.elasticsearch.core.elasticsearchtemplate; Intorg org.springframework.data.elasticsearch.core.query.nativesearchquerybuilder; Import org.springframework.data.elasticsearch.core.query.searchquery; Import org.springframework.web.bind.annotation.getMapping; 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; list <person> personlist = new ArrayList <>(900000); for(int i = 100000; i <1000000; i ++){double max = 0.00001; Double Min = 0.000001; RANDOM RANDOM = 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(lat);人の人= new Person(); person.setId(i); person.setname( "name" + i); person.setPhone( "tel" + i); person.setAddress(dlat + "、" + dlon); personList.add(person); } personservice.bulkindex(personlist); // SearchQuery SearchQuery = new NativesearchQueryBuilder()。 //リスト<記事>記事= elas、ticsearchtemplate.queryforlist(se、archquery、article.class); //(記事記事:記事){// system.out.println(article.tostring()); //} "add data"を返します。 } /*** 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( "address")。 GeodistancesortBuilder SORTBUILDER = SORTBUILDERS.GEODISTANCESORT( "ADDRESS").point(lat、lon).unit(distanceunit.meters).order(sortorder.asc); Pageable Pageable = new Pagerequest(0、50); NativesearchQueryBuilder Builder1 = new NativesearchQueryBuilder()。withfilter(builder).withsort(sortbuilder).withpageable(pageable); SearchQuery SearchQuery = builder1.build(); // QueryForListはデフォルトでパジネートされ、QueryForPageが使用されます。デフォルトは10 list <person> personlist = elasticsearchtemplate.queryforlist(searchquery、person.class)です。 system.out.println( "TimeCossuming:" +(System.CurrentTimemillis()-NowTime));返品パーソンリスト。 }} Controllerクラスを見ると、ADDメソッドでは、900,000のテストデータを挿入し、異なる緯度と経度のアドレスをランダムに生成します。
クエリ方法では、クエリから100メートル以内のクエリ条件を作成し、距離に応じてソートされ、ページごとに50アイテムをページングします。 Pageableが指定されていない場合、EstemplateのQueryForListはデフォルトで10です。これはソースコードを介して見ることができます。
プロジェクトを開始し、最初に追加を実行し、数十秒間の数百万のデータが挿入されるのを待ちます。
次に、クエリを実行して結果を確認します。
最初のクエリは300ms以上かかり、ESが自動的にメモリにキャッシュされたため、クエリの後に再び時間が大幅に低下しました。
ESが地理的位置のクエリを非常に迅速に完了することがわかります。近くの人やスコープクエリなどのクエリに適しています。
postScript:後で使用すると、Elasticsearchバージョン2.3では、上記の執筆方法に従ってジオタイプをインデックス化することはできません。 ESエントリは、マークされたジオフィールの代わりに文字列です。ここにソリューションのレコードがあり、文字列タイプをGeoPointに変更し、org.springframework.data.elasticsearch.core.geo.geopointの下にパッケージ化されています。次に、インデックスを作成してGeofieldに正しくマッピングするときに、マッピングメソッドを明示的に呼び出す必要があります。
次のように
if(!elasticsearchtemplate.indexists( "abc")){elasticsearchtemplate.createindex( "abc"); elasticsearchtemplate.putmapping(person.class); }上記はこの記事のすべての内容です。みんなの学習に役立つことを願っています。誰もがwulin.comをもっとサポートすることを願っています。