地理位置服务:ElasticSearchGeo实现-使⽤样例
地理位置服务:ElasticSearch Geo实现 - 使⽤样例
搭建Elasticsearch集
#单个进程中的最⼤线程数
vim /f
vm.max_map_count=262144
#⽴即⽣效
/sbin/sysctl -p
mkdir /itcast/tanhua/es-cluster/node01 -p
mkdir /itcast/tanhua/es-cluster/node02 -p
mkdir /itcast/tanhua/es-cluster/node03 -p
#复制资料⽬录下的jvm.options到node01、node02、node03⽬录
#在node01⽬录下,创建l⽂件,并输⼊如下内容:
cluster.name: es-tanhua-cluster
node.name: node01
node.master: true
node.data: true
network.host: 192.168.56.11
http.port: 9200
#在node02⽬录下,创建l⽂件,并输⼊如下内容:
cluster.name: es-tanhua-cluster
node.name: node02
node.master: true
node.data: true
network.host: 192.168.56.11
http.port: 9201
#在node03⽬录下,创建l⽂件,并输⼊如下内容:
cluster.name: es-tanhua-cluster
node.name: node03
node.master: true
node.data: true
network.host: 192.168.56.11
http.port: 9202
#创建容器
docker create --restart=always --name es-node01 --net host -v /itcast/tanhua/es-cluster/l:/usr/share/elasticsearch/l -v /itcast/tanhua/es-cluster/node01/jvm.options:/usr/share/elasticsearch/config/jvm.options -v es-c docker create --restart=always --name es-node02 --net host -v /itcast/tanhua/es-cluster/l:/usr/share/elasticsearch/l -v /itcast/tanhua/es-cluster/node02/jvm.options:/usr/share/elasticsearch/config/jvm.options -v es-c docker create --restart=always --name es-node03 --net host -v /itcast/tanhua/es-cluster/l:/usr/share/elasticsearch/l -v /itcast/tanhua/es-cluster/node03/jvm.options:/usr/share/elasticsearch/config/jvm.options -v es-c #启动容器
docker start es-node01 es-node02 es-node03
#或单个启动并查看⽇志
docker start es-node01 && docker logs -f es-node01
docker start es-node02 && docker logs -f es-node02
docker start es-node03 && docker logs -f es-node03
测试:
06.Elasticsearch实现位置查询之⼯程搭建
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="/POM/4.0.0"
xmlns:xsi="/2001/XMLSchema-instance"
xsi:schemaLocation="/POM/4.0.0 /xsd/maven-4.0.0.xsd">
<parent>
<artifactId>my-tanhua</artifactId>
<groupId>cn.itcast.tanhua</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>my-tanhua-elasticsearch</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--其他⼯具包依赖-->
<dependency>
<groupId>org.apachemons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
</project>
application.properties
spring.application.name = itcast-tanhua-elasticsearch
server.port = 18082
spring.data.elasticsearch.cluster-name=es-tanhua-cluster
spring.data.elasticsearch.cluster-nodes=192.168.56.11:9300,192.168.56.11:9301,192.168.56.11:9302
log4j.properties
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=[%t] [%c]-[%p] %m%n
启动类:
package com.tanhua.es;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ESApplication {
public static void main(String[] args) {
SpringApplication.run(ESApplication.class, args);
}
}
07.Elasticsearch实现位置查询之编码实现(更新⽤户地理位置) UserLocationES
package com.tanhua.es.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import GeoPoint;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
import org.springframework.data.elasticsearch.annotations.GeoPointField;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Document(indexName = "tanhua", type = "user_location", shards = 6, replicas = 2)
public class UserLocationES {
@Id
private Long userId; //⽤户id
@GeoPointField
private GeoPoint location; //x:经度 y:纬度
@Field(type = FieldType.Keyword)
private String address; //位置描述
@Field(type = FieldType.Long)
private Long created; //创建时间
@Field(type = FieldType.Long)
private Long updated; //更新时间
@Field(type = FieldType.Long)
private Long lastUpdated; //上次更新时间
}
UserLocationController
package com.ller;
import com.tanhua.es.pojo.UserLocationES;
import com.tanhua.es.service.UserLocationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("es/user/location")
public class UserLocationController {
@Autowired
private UserLocationService userLocationService;
/
**
* 更新⽤户的地理位置
*
* @param param
* @return
*/
@PostMapping
public ResponseEntity<UserLocationES> updateUserLocation(@RequestBody Map<String, Object> param) { try {
Long userId = Long.("userId").toString());
Double longitude = Double.("longitude").toString());
Double latitude = Double.("latitude").toString());
String address = ("address").toString();
boolean result = this.userLocationService.updateUserLocation(userId, longitude, latitude, address);
if (result) {
return ResponseEntity.ok(null);
}
} catch (NumberFormatException e) {
e.printStackTrace();
}
return ResponseEntity.status(HttpStatus.INSUFFICIENT_STORAGE).build();
}
}
UserLocationService
package com.tanhua.es.service;
import com.tanhua.es.pojo.UserLocationES;
import org.elasticsearch.action.update.UpdateRequest;
import GeoPoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ElasticsearchTemplate;
import org.springframework.query.*;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;
@Service
public class UserLocationService {
@Autowired
private ElasticsearchTemplate elasticsearchTemplate;
/**
* 更新⽤户的地理位置
*
* @param userId
* @param longitude
* @param latitude
* @param address
* @return
*/
public boolean updateUserLocation(Long userId, Double longitude, Double latitude, String address) {
try {
if (!this.elasticsearchTemplate.indexExists("tanhua")) {
// 创建索引
ateIndex(UserLocationES.class);
}
if (!peExists("tanhua", "user_location")) {
// 创建type
this.elasticsearchTemplate.putMapping(UserLocationES.class);
}
GetQuery getQuery = new GetQuery();
getQuery.String());
UserLocationES ul = this.elasticsearchTemplate.queryForObject(getQuery, UserLocationES.class);
if (null == ul) {
UserLocationES userLocationES = new UserLocationES();
userLocationES.setLocation(new GeoPoint(latitude, longitude));
userLocationES.setAddress(address);
userLocationES.setUserId(userId);
userLocationES.setCreated(System.currentTimeMillis());
userLocationES.Created());
userLocationES.Created());
IndexQuery indexQuery = new IndexQueryBuilder().withObject(userLocationES).build();
this.elasticsearchTemplate.index(indexQuery);
} else {
Map<String, Object> map = new HashMap<>();
map.put("lastUpdated", ul.getUpdated());
map.put("updated", System.currentTimeMillis());
map.put("address", address);
map.put("location", new GeoPoint(latitude, longitude));
UpdateRequest updateRequest = new UpdateRequest();
updateRequest.doc(map);
UpdateQuery updateQuery = new UpdateQueryBuilder()
.String())
.withClass(UserLocationES.class)
.withUpdateRequest(updateRequest).build();
this.elasticsearchTemplate.update(updateQuery);
}
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
}
08.Elasticsearch实现位置查询之编码实现(更新⽤户地理位置的单元则试)
package com.tanhua.es.service;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.st.context.SpringBootTest;
import st.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class TestUserLocationService {
@Autowired
private UserLocationService userLocationService;
@Test
public void testUpdateUserLocation() {
this.userLocationService.updateUserLocation(1L, 121.512253, 31.24094, "⾦茂⼤厦");
this.userLocationService.updateUserLocation(2L, 121.506377, 31.245105, "东⽅明珠⼴播电视塔");
this.userLocationService.updateUserLocation(10L, 121.508815, 31.243844, "陆家嘴地铁站");
this.userLocationService.updateUserLocation(12L, 121.511999, 31.239185, "上海中⼼⼤厦");
this.userLocationService.updateUserLocation(25L, 121.493444, 31.240513, "上海市公安局");
this.userLocationService.updateUserLocation(27L, 121.494108, 31.247011, "上海外滩美术馆");
this.userLocationService.updateUserLocation(30L, 121.462452, 31.253463, "上海⽕车站");
this.userLocationService.updateUserLocation(32L, 121.81509, 31.157478, "上海浦东国际机场");
this.userLocationService.updateUserLocation(34L, 121.327908, 31.20033, "虹桥⽕车站");
this.userLocationService.updateUserLocation(38L, 121.490155, 31.277476, "鲁迅公园");
this.userLocationService.updateUserLocation(40L, 121.425511, 31.227831, "中⼭公园");
this.userLocationService.updateUserLocation(43L, 121.594194, 31.207786, "张江⾼科");
}
}
09.Elasticsearch实现位置查询之编码实现(查询)
UserLocationController
/**
* 查询⽤户的地理位置
*
* @param userId
* @return
*/
@GetMapping("{userId}")
public ResponseEntity<UserLocationES> queryUserLocation(@PathVariable("userId") Long userId) {
try {
UserLocationES userLocationES = this.userLocationService.queryByUserId(userId);
if (null == userLocationES) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).build();
}
return ResponseEntity.ok(userLocationES);
} catch (Exception e) {
e.printStackTrace();
}
return ResponseEntity.status(HttpStatus.INSUFFICIENT_STORAGE).build();
}
/**
* 搜索附近的⼈
*
* @param param
* @return
*/
@PostMapping("list")
public ResponseEntity<List<UserLocationES>> queryUserFromLocation(@RequestBody Map<String, Object> param) {
try {
Double longitude = Double.("longitude").toString());
Double latitude = Double.("latitude").toString());
Double distance = Double.("distance").toString());
Integer page = ("page") == null ? 1 : Integer.("page").toString());
Integer pageSize = ("pageSize") == null ? 100 : Integer.("pageSize").toString());
Page<UserLocationES> userLocationES = this.userLocationService.queryUserFromLocation(longitude, latitude, distance, page, pageSize);
return ResponseEntity.Content());
} catch (NumberFormatException e) {
e.printStackTrace();
}
return ResponseEntity.status(HttpStatus.INSUFFICIENT_STORAGE).build();
}
UserLocationService
/**
* 查询⽤户的位置信息
*
* @param userId
* @return
*/
public UserLocationES queryByUserId(Long userId) {
GetQuery getQuery = new GetQuery();
getQuery.String());
return this.elasticsearchTemplate.queryForObject(getQuery, UserLocationES.class);
}
/**
* 根据位置搜索
*
* @param longitude 经度
* @param latitude 纬度
* @param distance 距离(⽶)
* @param page 页数
* @param pageSize 页⾯⼤⼩
*/
public Page<UserLocationES> queryUserFromLocation(Double longitude, Double latitude, Double distance, Integer page, Integer pageSize) {
String fieldName = "location";
// 实现了SearchQuery接⼝,⽤于组装QueryBuilder和SortBuilder以及Pageable等
NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
// 分页
PageRequest pageRequest = PageRequest.of(page - 1, pageSize);
nativeSearchQueryBuilder.withPageable(pageRequest);
// 定义bool查询
BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
// 以某点为中⼼,搜索指定范围
GeoDistanceQueryBuilder distanceQueryBuilder = new GeoDistanceQueryBuilder(fieldName);
distanceQueryBuilder.point(latitude, longitude);
// 定义查询单位:公⾥
distanceQueryBuilder.distance(distance / 1000, DistanceUnit.KILOMETERS);
boolQueryBuilder.must(distanceQueryBuilder);
nativeSearchQueryBuilder.withQuery(boolQueryBuilder);
/
/ 按距离升序
GeoDistanceSortBuilder distanceSortBuilder =
new GeoDistanceSortBuilder(fieldName, latitude, longitude);
distanceSortBuilder.unit(DistanceUnit.KILOMETERS); //设置单位
nativeSearchQueryBuilder.withSort(distanceSortBuilder);
return this.elasticsearchTemplate.queryForPage(nativeSearchQueryBuilder.build(), UserLocationES.class);
}
TestUserLocationService
@Test
public void testQueryByUserId() {
UserLocationES userLocationES = this.userLocationService.queryByUserId(1l);
System.out.println(userLocationES);
}
@Test
public void testQuery() {
Page<UserLocationES> userLocationPage = this.userLocationService.queryUserFromLocation(121.512253, 31.24094, 1000d, 1, 100);
userLocationPage.forEach(userLocationES -> {
System.out.println(userLocationES);
double distance = GeoDistance.ARC.calculate(31.24094, 121.512253, Location().getLat(), Location().getLon(), DistanceUnit.METERS);
System.out.println("距离我 : " + distance + "⽶");
});
}
location /user {
client_max_body_size 300m;
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
proxy_pass 127.0.0.1:18080;
}
location /users/header {
client_max_body_size 300m;
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
proxy_pass 127.0.0.1:18080;
}
location /es/ {
client_max_body_size 300m;
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
proxy_pass 127.0.0.1:18082;
}
location / {
client_max_body_size 300m;
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
proxy_pass 127.0.0.1:18081;
}
10.Elasticsearch版的dubbo服务实现
导⼊依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
配置RestTemplateConfig
package com.tanhua.fig;
import t.annotation.Bean;
import t.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.verter.StringHttpMessageConverter;
import org.springframework.web.client.RestTemplate;
import java.nio.charset.Charset;
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
RestTemplate restTemplate = new RestTemplate(factory);
// ⽀持中⽂编码
return restTemplate;
}
@Bean
public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setReadTimeout(5000);//单位为ms
factory.setConnectTimeout(5000);//单位为ms
return factory;
}
}
实现接⼝
application.properties增加配置:
server.port = 18083
# ES服务地址
es.server.url = 127.0.0.1/es/
ESUserLocationApiImpl
package com.tanhua.dubbo.server.api;
import com.fig.annotation.Service;
import com.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.de.ArrayNode;
import com.tanhua.dubbo.server.vo.UserLocationVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service(version = "2.0.0")
public class ESUserLocationApiImpl implements UserLocationApi {
private static final ObjectMapper MAPPER = new ObjectMapper();
@Autowired
private RestTemplate restTemplate;
@Value("${es.server.url}")
private String esServerUrl;
@Override
public String updateUserLocation(Long userId, Double longitude, Double latitude, String address) {
String url = this.esServerUrl + "user/location/";
Map<String, Object> param = new HashMap<>();
param.put("longitude", longitude);
param.put("latitude", latitude);
param.put("userId", userId);
param.put("address", address);
try {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> httpEntity = new HttpEntity<>(MAPPER.writeValueAsString(param), headers);
ResponseEntity<Void> responseEntity = stTemplate.postForEntity(url, httpEntity, Void.class);
if (StatusCodeValue() == 200) {
return "ok";
}
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return null;
}
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论