亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > Java > 正文

java 使用ElasticSearch完成百萬級數據查詢附近的人功能

2024-07-13 10:16:37
字體:
來源:轉載
供稿:網友

上一篇文章介紹了ElasticSearch使用Repository和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">   <modelVersion>4.0.0</modelVersion>    <groupId>com.tianyalei</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>     <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>    <dependencies>     <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>       <scope>test</scope>     </dependency>     <dependency>       <groupId>com.sun.jna</groupId>       <artifactId>jna</artifactId>       <version>3.0.9</version>     </dependency>   </dependencies>    <build>     <plugins>       <plugin>         <groupId>org.springframework.boot</groupId>         <artifactId>spring-boot-maven-plugin</artifactId>       </plugin>     </plugins>   </build>  </project> 

新建model類Person

package com.tianyalei.elasticsearch.model;  import org.springframework.data.annotation.Id; import org.springframework.data.elasticsearch.annotations.Document; import org.springframework.data.elasticsearch.annotations.GeoPointField;  import java.io.Serializable;  /**  * model類  */ @Document(indexName="elastic_search_project",type="person",indexStoreType="fs",shards=5,replicas=1,refreshInterval="-1") public class Person implements Serializable {   @Id   private int id;    private String name;    private String phone;    /**    * 地理位置經緯度    * lat緯度,lon經度 "40.715,-74.011"    * 如果用數組則相反[-73.983, 40.719]    */   @GeoPointField   private String address;    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 address) {     this.address = address;   } } 

我用address字段表示經緯度位置。注意,使用String[]和String分別來表示經緯度時是不同的,見注釋。

import com.tianyalei.elasticsearch.model.Person; import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;  public interface PersonRepository extends ElasticsearchRepository<Person, Integer> {  } 

看一下Service類,完成插入測試數據的功能,查詢的功能我放在Controller里了,為了方便查看,正常是應該放在Service里

package com.tianyalei.elasticsearch.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; import 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";    public Person add(Person 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<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().withId(person.getId() + "").withObject(person).build();          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 completed.");     } catch (Exception e) {       System.out.println("IndexerService.bulkIndex e;" + e.getMessage());       throw e;     }   } } 

注意看bulkIndex方法,這個是批量插入數據用的,bulk也是ES官方推薦使用的批量插入數據的方法。這里是每逢500的整數倍就bulk插入一次。

package 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.Pageable; import org.springframework.data.elasticsearch.core.ElasticsearchTemplate; import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; import org.springframework.data.elasticsearch.core.query.SearchQuery; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.List; import 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(lats);        Person person = new Person();       person.setId(i);       person.setName("名字" + i);       person.setPhone("電話" + i);       person.setAddress(dlat + "," + dlon);       personList.add(person);     }     personService.bulkIndex(personList);  //    SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(QueryBuilders.queryStringQuery("spring boot OR 書籍")).build(); //    List<Article> articles = elas、ticsearchTemplate.queryForList(se、archQuery, Article.class); //    for (Article article : articles) { //      System.out.println(article.toString()); //    }      return "添加數據";   }    /**    *    geo_distance: 查找距離某個中心點距離在一定范圍內的位置    geo_bounding_box: 查找某個長方形區域內的位置    geo_distance_range: 查找距離某個中心的距離在min和max之間的位置    geo_polygon: 查找位于多邊形內的地點。    sort可以用來排序    */   @GetMapping("/query")   public Object query() {     double lat = 39.929986;     double lon = 116.395645;      Long nowTime = System.currentTimeMillis();     //查詢某經緯度100米范圍內     GeoDistanceQueryBuilder builder = QueryBuilders.geoDistanceQuery("address").point(lat, lon)         .distance(100, DistanceUnit.METERS);      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("耗時:" + (System.currentTimeMillis() - nowTime));     return personList;   } } 

看Controller類,在add方法中,我們插入90萬條測試數據,隨機產生不同的經緯度地址。

在查詢方法中,我們構建了一個查詢100米范圍內、按照距離遠近排序,分頁每頁50條的查詢條件。如果不指明Pageable的話,ESTemplate的queryForList默認是10條,通過源碼可以看到。

啟動項目,先執行add,等待百萬數據插入,大概幾十秒。

然后執行查詢,看一下結果。

ElasticSearch,查詢附近的人,查詢

第一次查詢花費300多ms,再次查詢后時間就大幅下降,到30ms左右,因為ES已經自動緩存到內存了。

可見,ES完成地理位置的查詢還是非??斓摹_m用于查詢附近的人、范圍查詢之類的功能。

后記,在后來的使用中,Elasticsearch2.3版本時,按上面的寫法出現了geo類型無法索引的情況,進入es的為String,而不是標注的geofiled。在此記錄一下解決方法,將String類型修改為GeoPoint,且是org.springframework.data.elasticsearch.core.geo.GeoPoint包下的。然后需要在創建index時,顯式調用一下mapping方法,才能正確的映射為geofield。

如下

if (!elasticsearchTemplate.indexExists("abc")) {       elasticsearchTemplate.createIndex("abc");       elasticsearchTemplate.putMapping(Person.class);     } 

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VeVb武林網。


注:相關教程知識閱讀請移步到JAVA教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
8090理伦午夜在线电影| 欧美成年人视频网站| 亚洲一区二区三区xxx视频| 国产香蕉97碰碰久久人人| 91sa在线看| 97超碰国产精品女人人人爽| 国产成人97精品免费看片| 国产精品久久久久久久久| 国模精品视频一区二区| 亚洲天堂免费在线| 国产精品夜色7777狼人| 日韩在线观看av| 亚洲aa中文字幕| 性欧美激情精品| 国产亚洲欧美aaaa| 韩日欧美一区二区| 亚洲女人初尝黑人巨大| 一级做a爰片久久毛片美女图片| 精品精品国产国产自在线| 欧美电影免费在线观看| 亚洲另类欧美自拍| 8090理伦午夜在线电影| 在线日韩第一页| 日本韩国在线不卡| 久久九九全国免费精品观看| 国产精品男人爽免费视频1| 久久九九国产精品怡红院| 2019中文字幕在线| 亚洲精品美女在线观看| 97视频在线播放| 91在线视频精品| 国产成人欧美在线观看| 九九热视频这里只有精品| 亚洲国产欧美精品| 2019中文在线观看| 色99之美女主播在线视频| 久久久久亚洲精品成人网小说| 97国产精品视频| 色狠狠av一区二区三区香蕉蜜桃| 欧洲精品毛片网站| 国产一区二区三区视频| 亚州av一区二区| 这里只有精品视频在线| www.国产精品一二区| 欧美日韩国产丝袜另类| 日韩在线视频线视频免费网站| 性欧美长视频免费观看不卡| 中文字幕精品一区久久久久| 亚洲国产精品国自产拍av秋霞| 国产精品高潮呻吟久久av无限| 日韩美女主播视频| 亚洲日本成人网| 欧美中文字幕在线| 中文字幕在线亚洲| 亚洲精品小视频| 国产精品日日摸夜夜添夜夜av| 欧美裸体视频网站| 久久夜精品香蕉| 国产欧美在线观看| 97视频在线观看免费| 亚洲桃花岛网站| 日韩国产高清视频在线| 一道本无吗dⅴd在线播放一区| 欧美激情亚洲国产| 日韩女优人人人人射在线视频| 亚洲国产精久久久久久久| 777午夜精品福利在线观看| 欧美日韩国产精品一区二区三区四区| 日韩亚洲在线观看| 国产成人精品综合久久久| 国产精品久久久久影院日本| 欧美精品久久久久久久| 精品久久久av| 国产拍精品一二三| 中文字幕日韩欧美在线视频| 国产午夜精品视频免费不卡69堂| 最近2019中文免费高清视频观看www99| 深夜福利国产精品| 国产精品久久久久久久久久| 午夜精品久久久99热福利| 国产精品一区二区三区在线播放| 欧美亚洲国产另类| 亚洲精品国精品久久99热一| 亚洲综合在线播放| 国产欧美欧洲在线观看| 日韩欧美国产激情| 国产精品久久国产精品99gif| 国产精品99久久99久久久二8| 亚洲成人激情视频| 欧美在线激情视频| 中文字幕欧美日韩| 欧美极品美女视频网站在线观看免费| 亚洲亚裔videos黑人hd| 亚洲国产精品专区久久| 久久久久久美女| 成人h视频在线| 亚洲自拍偷拍视频| 97在线视频观看| 欧美久久精品午夜青青大伊人| 国产噜噜噜噜久久久久久久久| 亚洲最新在线视频| 91九色国产社区在线观看| 欧美日韩国产一中文字不卡| 国产亚洲欧美一区| 九九热精品视频| 97在线视频一区| 国产精品一区二区久久国产| 日韩在线视频线视频免费网站| 91国产精品91| 欧美性生交xxxxxdddd| 国产精品盗摄久久久| 色综合男人天堂| 国产福利视频一区二区| 91影院在线免费观看视频| 庆余年2免费日韩剧观看大牛| 亚洲国产美女久久久久| 国产精品久久久av久久久| 精品视频一区在线视频| 国产免费一区二区三区在线能观看| 欧美成aaa人片在线观看蜜臀| 青青草99啪国产免费| 在线电影欧美日韩一区二区私密| 国产成人福利视频| 理论片在线不卡免费观看| 亚洲伦理中文字幕| 欧美电影在线观看网站| 欧美人与性动交| 亚洲国产高潮在线观看| 国产精品视频免费在线| 欧美成人免费一级人片100| 欧美夫妻性生活视频| 欧美日韩视频在线| 欧美黄色三级网站| 狠狠色香婷婷久久亚洲精品| 午夜免费日韩视频| 青草青草久热精品视频在线观看| 亚洲高清久久久久久| 日韩精品免费在线视频观看| 成人444kkkk在线观看| 国产大片精品免费永久看nba| 91视频国产一区| 久久久久久网站| 欧美激情亚洲另类| 国产成人精品电影久久久| 国产精品高潮视频| 国产视频精品自拍| 亚洲午夜未满十八勿入免费观看全集| 欧美大码xxxx| 高清视频欧美一级| 久久精品小视频| 国产亚洲a∨片在线观看| 国产精品igao视频| 国产精品偷伦一区二区| 欧美成人精品三级在线观看| 一本大道久久加勒比香蕉| 国产视频综合在线| 欧美极品xxxx| 亚洲第一在线视频| 久久久电影免费观看完整版| 亚洲激情第一页| 国产成人精品一区二区三区| 欧美性资源免费| 中文字幕亚洲欧美日韩在线不卡| 一本色道久久88综合日韩精品|