版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
Elasticsearch地理坐标与百度地图
想要使用百度地图,可以在百度地图的控制台免费注册,然后使用,控制台地址:http://lbsyun.baidu.com/apiconsole/center#/home
我使用的百度地图版本是v4
LBS.云服务接口文档:http://lbsyun.baidu.com/index.php?title=lbscloud/api/geodataV4
API接口初始化
BAIDU_MAP_KEY 为自己的ak,需要在控制台创建应用
private static final String BAIDU_MAP_KEY = "aSg2jDQuYk9PaeeRqCb7rG6seU123456";
private static final String BAIDU_MAP_GEOCONV_API = "http://api.map.baidu.com/geocoding/v3/?";
// 百度地图API :http://lbsyun.baidu.com/index.php?title=webapi/guide/webservice-geocoding
//http://api.map.baidu.com/geocoding/v3/?address=%E5%8C%97%E4%BA%AC%E5%B8%82%E6%B5%B7%E6%B7%80%E5%8C%BA%E4%B8%8A%E5%9C%B0%E5%8D%81%E8%A1%9710%E5%8F%B7&output=json&ak=qSg2jDQuYk9PaVBRqCb7rG6seU0gmBsT&callback=showLocation
/**
* POI数据管理接口
*/
private static final String LBS_CREATE_API = "http://api.map.baidu.com/geodata/v4/poi/create";
private static final String LBS_QUERY_API = "http://api.map.baidu.com/geodata/v4/poi/list?";
private static final String LBS_UPDATE_API = "http://api.map.baidu.com/geodata/v4/poi/update";
private static final String LBS_DELETE_API = "http://api.map.baidu.com/geodata/v4/poi/delete";
上传坐标
虎鲸数据管理平台 v3链接:http://lbsyun.baidu.com/data/mydata#/?_k=awsg5v
public ServiceResult lbsUpload(BaiduMapLocation location, String title,
String address,
long houseId, int price,
int area) {
HttpClient httpClient = HttpClients.createDefault();
List<NameValuePair> nvps = new ArrayList<>();
nvps.add(new BasicNameValuePair("latitude", String.valueOf(location.getLatitude())));
nvps.add(new BasicNameValuePair("longitude", String.valueOf(location.getLongitude())));
nvps.add(new BasicNameValuePair("coord_type", "3")); // 百度坐标系
nvps.add(new BasicNameValuePair("geotable_id", "1000006426"));
// 需要在虎鲸数据管理平台 v3中创建表,除了基本的字段增加houseId、price、area
nvps.add(new BasicNameValuePair("ak", BAIDU_MAP_KEY));
nvps.add(new BasicNameValuePair("houseId", String.valueOf(houseId)));
nvps.add(new BasicNameValuePair("price", String.valueOf(price)));
nvps.add(new BasicNameValuePair("area", String.valueOf(area)));
nvps.add(new BasicNameValuePair("title", title));
nvps.add(new BasicNameValuePair("address", address));
HttpPost post;
JsonNode isjsonNode = isLbsDataExists(houseId);
if (null!=isjsonNode) {
List<JsonNode> nodeList =isjsonNode.findValues("pois");
if(null!=nodeList&&!nodeList.isEmpty()) {
JsonNode jsonNode =nodeList.get(0);
if(null!=jsonNode.get("id")){
String id = jsonNode.get("id").asText();
nvps.add(new BasicNameValuePair("id", id));
post = new HttpPost(LBS_UPDATE_API);
}else {
post = new HttpPost(LBS_CREATE_API);
}
}else {
post = new HttpPost(LBS_CREATE_API);
}
} else {
post = new HttpPost(LBS_CREATE_API);
}
try {
post.setEntity(new UrlEncodedFormEntity(nvps, "UTF-8"));
HttpResponse response = httpClient.execute(post);
String result = EntityUtils.toString(response.getEntity(), "UTF-8");
if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
logger.error("Can not upload lbs data for response: " + result);
return new ServiceResult(false, "Can not upload baidu lbs data");
} else {
JsonNode jsonNode = objectMapper.readTree(result);
int status = jsonNode.get("status").asInt();
if (status != 0) {
String message = jsonNode.get("message").asText();
logger.error("Error to upload lbs data for status: {}, and message: {}", status, message);
return new ServiceResult(false, "Error to upload lbs data");
} else {
// int id = jsonNode.get("id").asInt();
return ServiceResult.success();
}
}
} catch (IOException e) {
e.printStackTrace();
}
return new ServiceResult(false);
}
判断坐标是否存在
private JsonNode isLbsDataExists(Long houseId) {
HttpClient httpClient = HttpClients.createDefault();
StringBuilder sb = new StringBuilder(LBS_QUERY_API);
sb.append("geotable_id=").append("1000006426").append("&")
.append("ak=").append(BAIDU_MAP_KEY).append("&")
.append("houseId=").append(houseId).append(",").append(houseId);
HttpGet get = new HttpGet(sb.toString());
try {
HttpResponse response = httpClient.execute(get);
String result = EntityUtils.toString(response.getEntity(), "UTF-8");
if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
logger.error("Can not get lbs data for response: " + result);
return null;
}
JsonNode jsonNode = objectMapper.readTree(result);
int status = jsonNode.get("status").asInt();
if (status != 0) {
logger.error("Error to get lbs data for status: " + status);
return null;
} else {
long size = jsonNode.get("size").asLong();
if (size > 0) {
return jsonNode;
} else {
return null;
}
}
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
移除坐标
public ServiceResult removeLbs(Long houseId) {
HttpClient httpClient = HttpClients.createDefault();
List<NameValuePair> nvps = new ArrayList<>();
nvps.add(new BasicNameValuePair("geotable_id", "1000006426"));
nvps.add(new BasicNameValuePair("ak", BAIDU_MAP_KEY));
nvps.add(new BasicNameValuePair("houseId", String.valueOf(houseId)));
JsonNode isjsonNode = isLbsDataExists(houseId);
if(null!=isjsonNode){
List<JsonNode> nodeList =isjsonNode.findValues("pois");
if(null!=nodeList&&nodeList.size()>0){
Optional.ofNullable(nodeList.get(0).get("id")).ifPresent(n->{
String id = nodeList.get(0).get("id").asText();
nvps.add(new BasicNameValuePair("id", id));
});
}
}
HttpPost delete = new HttpPost(LBS_DELETE_API);
try {
delete.setEntity(new UrlEncodedFormEntity(nvps, "UTF-8"));
HttpResponse response = httpClient.execute(delete);
String result = EntityUtils.toString(response.getEntity(), "UTF-8");
if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
logger.error("Error to delete lbs data for response: " + result);
return new ServiceResult(false);
}
JsonNode jsonNode = objectMapper.readTree(result);
int status = jsonNode.get("status").asInt();
if (status != 0) {
String message = jsonNode.get("message").asText();
logger.error("Error to delete lbs data for message: " + message);
return new ServiceResult(false, "Error to delete lbs data for: " + message);
}
return ServiceResult.success();
} catch (IOException e) {
logger.error("Error to delete lbs data.", e);
return new ServiceResult(false);
}
}
通过地址获取地图坐标
@Override
public ServiceResult<BaiduMapLocation> getBaiduMapLocation(String city, String address) {
String encodeAddress;
try {
encodeAddress = URLEncoder.encode(address, "UTF-8");
} catch (UnsupportedEncodingException e) {
logger.error("Error to encode house address", e);
return new ServiceResult<BaiduMapLocation>(false, "Error to encode hosue address");
}
HttpClient httpClient = HttpClients.createDefault();
StringBuilder sb = new StringBuilder(BAIDU_MAP_GEOCONV_API);
sb.append("address=").append(encodeAddress).append("&")
.append("output=json&")
.append("ak=").append(BAIDU_MAP_KEY);
HttpGet get = new HttpGet(sb.toString());
try {
HttpResponse response = httpClient.execute(get);
if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
return new ServiceResult<BaiduMapLocation>(false, "Can not get baidu map location");
}
String result = EntityUtils.toString(response.getEntity(), "UTF-8");
JsonNode jsonNode = objectMapper.readTree(result);
int status = jsonNode.get("status").asInt();
if (status != 0) {
return new ServiceResult<BaiduMapLocation>(false, "Error to get map location for status: " + status);
} {
BaiduMapLocation location = new BaiduMapLocation();
JsonNode jsonLocation = jsonNode.get("result").get("location");
location.setLongitude(jsonLocation.get("lng").asDouble());
location.setLatitude(jsonLocation.get("lat").asDouble());
return ServiceResult.of(location);
}
} catch (IOException e) {
logger.error("Error to fetch baidumap api", e);
return new ServiceResult<BaiduMapLocation>(false, "Error to fetch baidumap api");
}
}
Elasticsearch 的geoBoundingBoxQuery查询地理坐标信息
Elasticsearch的地图坐标JavaApi:
https://www.elastic.co/guide/en/elasticsearch/client/java-api/2.4/java-geo-queries.html
首先在Elasticsearch中增加索引坐标属性
例:
{
"settings": {
"number_of_replicas": 0,
"number_of_shards": 5,
"index.store.type": "niofs",
"index.query.default_field": "title",
"index.unassigned.node_left.delayed_timeout": "5m"
},
"mappings": {
"house": {
"dynamic": "strict",
"_all": {
"enabled": false
},
"properties": {
"Id": {
"type": "long"
},
"title": {
"type": "text",
"index": "analyzed",
"analyzer": "ik_smart",
"search_analyzer": "ik_smart"
},
"suggest": {
"type": "completion"
},
"location": {
"type": "geo_point"
}
}
}
}
}
可以通过postman直接post请求http://192.168.108.102:9200/test,在body中增加索引json。
然后查看head插件中是否生成成功。
java查询地理区域代码:
public ServiceMultiResult<Long> mapQuery(MapSearch mapSearch) {
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
boolQueryBuilder.filter(QueryBuilders.termQuery(HouseIndexKey.CITY_EN_NAME,mapSearch.getCityEnName()));
boolQueryBuilder.filter(
geoBoundingBoxQuery("location")
.topLeft(mapSearch.getLeftLatitude(),mapSearch.getLeftLongitude())
.bottomRight(mapSearch.getRightLatitude(),mapSearch.getRightLongitude())
);
SearchRequestBuilder searchRequestBuilder = this.esClient.prepareSearch(INDEX_NAME)
.setTypes(INDEX_TYPE)
.setQuery(boolQueryBuilder)
.addSort(HouseSort.getSortKey(mapSearch.getOrderBy()),SortOrder.valueOf(mapSearch.getOrderDirection()))
.setFrom(mapSearch.getStart())
.setSize(mapSearch.getSize());
List<Long> houseIds = new ArrayList<>();
SearchResponse response = searchRequestBuilder.get();
if(response.status()!=RestStatus.OK){
logger.warn("Search status is not ok for "+ searchRequestBuilder);
return new ServiceMultiResult<>(0,houseIds);
}
for (SearchHit hit : response.getHits()) {
houseIds.add(Longs.tryParse(String.valueOf(hit.getSource().get(HouseIndexKey.HOUSE_ID))));
}
return new ServiceMultiResult<>(response.getHits().getTotalHits(),houseIds);
}