博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
使用elasticsearch1.5.2实现查找附近的人
阅读量:7217 次
发布时间:2019-06-29

本文共 14213 字,大约阅读时间需要 47 分钟。

hot3.png

pom.xml:

4.0.0
com.heli
ElasticSearch
0.0.1-SNAPSHOT
jar
ElasticSearch
http://maven.apache.org
UTF-8
1.5.2
4.10.4
org.elasticsearch
elasticsearch
${es.version}
junit
junit
4.8.2
test

用户实体:

package com.heli.es;public class User {	private long id;// id	private String name;// 姓名	private double lat;// 纬度	private double lon;// 经度	private double[] location;// hashcode		public User(long id, String name, double lat, double lon) {		super();		this.id = id;		this.name = name;		this.lat = lat;		this.lon = lon;	}	public long getId() {		return id;	}	public void setId(long id) {		this.id = id;	}	public String getName() {		return name;	}	public void setName(String name) {		this.name = name;	}	public double getLat() {		return lat;	}	public void setLat(double lat) {		this.lat = lat;	}	public double getLon() {		return lon;	}	public void setLon(double lon) {		this.lon = lon;	}	public double[] getLocation() {		return location;	}	public void setLocation(double[] location) {		this.location = location;	}}

测试类:

package com.heli.es;import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;import static org.elasticsearch.index.query.FilterBuilders.geoDistanceRangeFilter;import java.io.IOException;import java.math.BigDecimal;import java.text.DecimalFormat;import java.util.ArrayList;import java.util.List;import java.util.Map;import java.util.Random;import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse;import org.elasticsearch.action.bulk.BulkRequestBuilder;import org.elasticsearch.action.bulk.BulkResponse;import org.elasticsearch.action.index.IndexRequest;import org.elasticsearch.action.search.SearchRequestBuilder;import org.elasticsearch.action.search.SearchResponse;import org.elasticsearch.client.Client;import org.elasticsearch.client.Requests;import org.elasticsearch.client.transport.TransportClient;import org.elasticsearch.common.geo.GeoDistance;import org.elasticsearch.common.transport.InetSocketTransportAddress;import org.elasticsearch.common.unit.DistanceUnit;import org.elasticsearch.common.xcontent.XContentBuilder;import org.elasticsearch.common.xcontent.XContentFactory;import org.elasticsearch.index.query.FilterBuilder;import org.elasticsearch.search.SearchHit;import org.elasticsearch.search.SearchHits;import org.elasticsearch.search.sort.GeoDistanceSortBuilder;import org.elasticsearch.search.sort.SortBuilders;import org.elasticsearch.search.sort.SortOrder;/** * 实现附近的人功能,最大限额1000人,1米到100米范围内的人 */public class ES4 {	// 创建索引	public static void createIndex(String indexName, String indexType) throws IOException {		Client esClient = new TransportClient().addTransportAddress(new InetSocketTransportAddress("127.0.0.1", 9300));		// 创建Mapping		XContentBuilder mapping = createMapping(indexType);		System.out.println("mapping:" + mapping.string());		// 创建一个空索引		esClient.admin().indices().prepareCreate(indexName).execute().actionGet();		PutMappingRequest putMapping = Requests.putMappingRequest(indexName).type(indexType).source(mapping);		PutMappingResponse response = esClient.admin().indices().putMapping(putMapping).actionGet();		if (!response.isAcknowledged()) {			System.out.println("Could not define mapping for type [" + indexName + "]/[" + indexType + "].");		} else {			System.out.println("Mapping definition for [" + indexName + "]/[" + indexType + "] succesfully created.");		}	}	// 创建mapping	public static XContentBuilder createMapping(String indexType) {		XContentBuilder mapping = null;		try {			mapping = jsonBuilder().startObject()					// 索引库名(类似数据库中的表)					.startObject(indexType).startObject("properties")					// ID					.startObject("id").field("type", "long").endObject()					// 姓名					.startObject("name").field("type", "string").endObject()					// 位置					.startObject("location").field("type", "geo_point").endObject()			.endObject().endObject().endObject();		} catch (IOException e) {			e.printStackTrace();		}		return mapping;	}	// 添加数据	public static Integer addIndexData100000(String indexName, String indexType) {		Client client = new TransportClient().addTransportAddress(new InetSocketTransportAddress("127.0.0.1", 9300));		List
 cityList = new ArrayList
(); double lat = 39.929986; double lon = 116.395645; for (int i = 0; i < 100000; 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); User city1 = new User(i, "郭德纲"+i, dlat, dlon); cityList.add(obj2JsonUserData(city1)); } // 创建索引库 List
 requests = new ArrayList
(); for (int i = 0; i < cityList.size(); i++) { IndexRequest request = client.prepareIndex(indexName, indexType).setSource(cityList.get(i)).request(); requests.add(request); } // 批量创建索引 BulkRequestBuilder bulkRequest = client.prepareBulk(); for (IndexRequest request : requests) { bulkRequest.add(request); } BulkResponse bulkResponse = bulkRequest.execute().actionGet(); if (bulkResponse.hasFailures()) { System.out.println("批量创建索引错误!"); } return bulkRequest.numberOfActions(); } public static String obj2JsonUserData(User user) { String jsonData = null; try { // 使用XContentBuilder创建json数据 XContentBuilder jsonBuild = XContentFactory.jsonBuilder(); jsonBuild.startObject().field("id", user.getId()).field("name", user.getName()).startArray("location").value(user.getLat()).value(user.getLon()).endArray() .endObject(); jsonData = jsonBuild.string(); System.out.println(jsonData); } catch (IOException e) { e.printStackTrace(); } return jsonData; } // 获取附近的人 public static void testGetNearbyPeople(Client client, String index, String type, double lat, double lon) { SearchRequestBuilder srb = client.prepareSearch(index).setTypes(type); srb.setFrom(0).setSize(1000);//1000人 // lon, lat位于谦的坐标,查询距离于谦1米到1000米 FilterBuilder builder = geoDistanceRangeFilter("location").point(lon, lat).from("1m").to("100m").optimizeBbox("memory").geoDistance(GeoDistance.PLANE); srb.setPostFilter(builder); // 获取距离多少公里 这个才是获取点与点之间的距离的 GeoDistanceSortBuilder sort = SortBuilders.geoDistanceSort("location"); sort.unit(DistanceUnit.METERS); sort.order(SortOrder.ASC); sort.point(lon, lat); srb.addSort(sort); SearchResponse searchResponse = srb.execute().actionGet(); SearchHits hits = searchResponse.getHits(); SearchHit[] searchHists = hits.getHits();  // 搜索耗时        Float usetime = searchResponse.getTookInMillis() / 1000f; System.out.println("于谦附近的人(" + hits.getTotalHits() + "个),耗时("+usetime+"秒):"); for (SearchHit hit : searchHists) { String name = (String) hit.getSource().get("name"); List
 location = (List
)hit.getSource().get("location"); // 获取距离值,并保留两位小数点 BigDecimal geoDis = new BigDecimal((Double) hit.getSortValues()[0]); Map
 hitMap = hit.getSource(); // 在创建MAPPING的时候,属性名的不可为geoDistance。 hitMap.put("geoDistance", geoDis.setScale(0, BigDecimal.ROUND_HALF_DOWN)); System.out.println(name+"的坐标:"+location + "他距离于谦" + hit.getSource().get("geoDistance") + DistanceUnit.METERS.toString()); } } public static void main(String[] args) throws IOException { Client client = new TransportClient().addTransportAddress(new InetSocketTransportAddress("127.0.0.1", 9300)); String index = "es"; String type = "people"; //createIndex(index, type); //addIndexData100000(index, type); double lat = 39.929986; double lon = 116.395645; long start = System.currentTimeMillis(); //query("郭", index, type); testGetNearbyPeople(client, index, type, lat, lon); long end = System.currentTimeMillis(); System.out.println((end - start) + "毫秒"); //client.close();// 1.5.2用完不用关闭 }}

查询结果:

于谦附近的人(69个),耗时(0.016秒):郭德纲17413的坐标:[39.929999, 116.395658]他距离于谦2m郭德纲79407的坐标:[39.930006, 116.395665]他距离于谦2m郭德纲26009的坐标:[39.93003, 116.395689]他距离于谦5m郭德纲90577的坐标:[39.930041, 116.3957]他距离于谦7m郭德纲4479的坐标:[39.930049, 116.395708]他距离于谦8m郭德纲59538的坐标:[39.930068, 116.395727]他距离于谦10m郭德纲56225的坐标:[39.930072, 116.395731]他距离于谦10m郭德纲78623的坐标:[39.930075, 116.395734]他距离于谦11m郭德纲21402的坐标:[39.930092, 116.395751]他距离于谦13m郭德纲98117的坐标:[39.930098, 116.395757]他距离于谦14m郭德纲92957的坐标:[39.9301, 116.395759]他距离于谦14m郭德纲75291的坐标:[39.930101, 116.39576]他距离于谦14m郭德纲84154的坐标:[39.930121, 116.39578]他距离于谦16m郭德纲73369的坐标:[39.93016, 116.395819]他距离于谦21m郭德纲38979的坐标:[39.930174, 116.395833]他距离于谦23m郭德纲78569的坐标:[39.930193, 116.395852]他距离于谦25m郭德纲15100的坐标:[39.930207, 116.395866]他距离于谦27m郭德纲3864的坐标:[39.930218, 116.395877]他距离于谦28m郭德纲66276的坐标:[39.930237, 116.395896]他距离于谦30m郭德纲90141的坐标:[39.930243, 116.395902]他距离于谦31m郭德纲29377的坐标:[39.930249, 116.395908]他距离于谦32m郭德纲54727的坐标:[39.930253, 116.395912]他距离于谦32m郭德纲10456的坐标:[39.930292, 116.395951]他距离于谦37m郭德纲48968的坐标:[39.930298, 116.395957]他距离于谦38m郭德纲20625的坐标:[39.930305, 116.395964]他距离于谦39m郭德纲58066的坐标:[39.930307, 116.395966]他距离于谦39m郭德纲76596的坐标:[39.930308, 116.395967]他距离于谦39m郭德纲73185的坐标:[39.930323, 116.395982]他距离于谦41m郭德纲26093的坐标:[39.930331, 116.39599]他距离于谦42m郭德纲76719的坐标:[39.930331, 116.39599]他距离于谦42m郭德纲27200的坐标:[39.930337, 116.395996]他距离于谦43m郭德纲48983的坐标:[39.930337, 116.395996]他距离于谦43m郭德纲21808的坐标:[39.930356, 116.396015]他距离于谦45m郭德纲70386的坐标:[39.930356, 116.396015]他距离于谦45m郭德纲56140的坐标:[39.93036, 116.396019]他距离于谦45m郭德纲19567的坐标:[39.930365, 116.396024]他距离于谦46m郭德纲9499的坐标:[39.930366, 116.396025]他距离于谦46m郭德纲11682的坐标:[39.930381, 116.39604]他距离于谦48m郭德纲19372的坐标:[39.930382, 116.396041]他距离于谦48m郭德纲12508的坐标:[39.930383, 116.396042]他距离于谦48m郭德纲56554的坐标:[39.930385, 116.396044]他距离于谦48m郭德纲79324的坐标:[39.930389, 116.396048]他距离于谦49m郭德纲30910的坐标:[39.930394, 116.396053]他距离于谦50m郭德纲45095的坐标:[39.930412, 116.396071]他距离于谦52m郭德纲73533的坐标:[39.930422, 116.396081]他距离于谦53m郭德纲46509的坐标:[39.930422, 116.396081]他距离于谦53m郭德纲81262的坐标:[39.93044, 116.396099]他距离于谦55m郭德纲30077的坐标:[39.930448, 116.396107]他距离于谦56m郭德纲61049的坐标:[39.930456, 116.396115]他距离于谦57m郭德纲16607的坐标:[39.930458, 116.396117]他距离于谦57m郭德纲50464的坐标:[39.930467, 116.396126]他距离于谦58m郭德纲7272的坐标:[39.930468, 116.396127]他距离于谦59m郭德纲82133的坐标:[39.93047, 116.396129]他距离于谦59m郭德纲46350的坐标:[39.930472, 116.396131]他距离于谦59m郭德纲40185的坐标:[39.930502, 116.396161]他距离于谦63m郭德纲28020的坐标:[39.930515, 116.396174]他距离于谦64m郭德纲75873的坐标:[39.93052, 116.396179]他距离于谦65m郭德纲83959的坐标:[39.930527, 116.396186]他距离于谦66m郭德纲5175的坐标:[39.930529, 116.396188]他距离于谦66m郭德纲15511的坐标:[39.930531, 116.39619]他距离于谦66m郭德纲61721的坐标:[39.930535, 116.396194]他距离于谦67m郭德纲54860的坐标:[39.930549, 116.396208]他距离于谦68m郭德纲38391的坐标:[39.93055, 116.396209]他距离于谦69m郭德纲5603的坐标:[39.930555, 116.396214]他距离于谦69m郭德纲70588的坐标:[39.930579, 116.396238]他距离于谦72m郭德纲12256的坐标:[39.930583, 116.396242]他距离于谦73m郭德纲93219的坐标:[39.930598, 116.396257]他距离于谦74m郭德纲80353的坐标:[39.930607, 116.396266]他距离于谦75m郭德纲19737的坐标:[39.930617, 116.396276]他距离于谦77m82毫秒

注:server 和client版本使用的是1.5.2,如果server版本用elasticsearch-rtf-master,sort的时候总是报:

Exception in thread "main" org.elasticsearch.action.search.SearchPhaseExecutionException: Failed to execute phase [query], all shards failed; shardFailures {[alee59cPQNuzRP4go6-5vw][testes][4]: SearchParseException[[testes][4]: from[-1],size[-1]: Parse Failure [Failed to parse source [{"post_filter":{"geo_distance_range":{"location":"wx4g0th9p0gk","from":"1km","to":"2000km","include_lower":true,"include_upper":true,"distance_type":"arc","optimize_bbox":"memory"}},"sort":[{"_geo_distance":{"location":[{"lat":39.929986,"lon":116.395645}],"unit":"km","distance_type":"arc"}}]}]]]; nested: ElasticsearchParseException[Numeric value expected]; }{[alee59cPQNuzRP4go6-5vw][testes][0]: SearchParseException[[testes][0]: from[-1],size[-1]: Parse Failure [Failed to parse source [{"post_filter":{"geo_distance_range":{"location":"wx4g0th9p0gk","from":"1km","to":"2000km","include_lower":true,"include_upper":true,"distance_type":"arc","optimize_bbox":"memory"}},"sort":[{"_geo_distance":{"location":[{"lat":39.929986,"lon":116.395645}],"unit":"km","distance_type":"arc"}}]}]]]; nested: ElasticsearchParseException[Numeric value expected]; }{[alee59cPQNuzRP4go6-5vw][testes][1]: SearchParseException[[testes][1]: from[-1],size[-1]: Parse Failure [Failed to parse source [{"post_filter":{"geo_distance_range":{"location":"wx4g0th9p0gk","from":"1km","to":"2000km","include_lower":true,"include_upper":true,"distance_type":"arc","optimize_bbox":"memory"}},"sort":[{"_geo_distance":{"location":[{"lat":39.929986,"lon":116.395645}],"unit":"km","distance_type":"arc"}}]}]]]; nested: ElasticsearchParseException[Numeric value expected]; }{[alee59cPQNuzRP4go6-5vw][testes][2]: SearchParseException[[testes][2]: from[-1],size[-1]: Parse Failure [Failed to parse source [{"post_filter":{"geo_distance_range":{"location":"wx4g0th9p0gk","from":"1km","to":"2000km","include_lower":true,"include_upper":true,"distance_type":"arc","optimize_bbox":"memory"}},"sort":[{"_geo_distance":{"location":[{"lat":39.929986,"lon":116.395645}],"unit":"km","distance_type":"arc"}}]}]]]; nested: ElasticsearchParseException[Numeric value expected]; }{[alee59cPQNuzRP4go6-5vw][testes][3]: SearchParseException[[testes][3]: from[-1],size[-1]: Parse Failure [Failed to parse source [{"post_filter":{"geo_distance_range":{"location":"wx4g0th9p0gk","from":"1km","to":"2000km","include_lower":true,"include_upper":true,"distance_type":"arc","optimize_bbox":"memory"}},"sort":[{"_geo_distance":{"location":[{"lat":39.929986,"lon":116.395645}],"unit":"km","distance_type":"arc"}}]}]]]; nested: ElasticsearchParseException[Numeric value expected]; }

 换成1.5.2结果就好了,还有

.point(lon, lat)

  必须经度在前,纬度在后,不然查询为空,跟一朋友聊说这个可能是个bug

  另外查询速度太慢,应该哪个地方配置的问题,经过试验,原来创建client消耗了1秒左右,10万个基数查询82毫秒,非常快

转载于:https://my.oschina.net/ydsakyclguozi/blog/515931

你可能感兴趣的文章
Mono为何能跨平台?聊聊CIL(MSIL)
查看>>
安装scrapy问题:-bash:scrapy:command not found
查看>>
CentOS7 重置root密码
查看>>
博客作业四
查看>>
Scanner 输入---从键盘输入两个数进行相加
查看>>
test
查看>>
说无可说
查看>>
mysql 语句优化
查看>>
SCP 命令参数使用详解(最详细使用指南)
查看>>
windows cmd color setup
查看>>
一些问题
查看>>
ubuntu配置cudnn
查看>>
P1242 新汉诺塔 && UVA10795 A Different Task
查看>>
从零开始学习PYTHON3讲义(十一)计算器升级啦
查看>>
从零开始学习PYTHON3讲义(三)写第一个程序
查看>>
WebGis设计模式
查看>>
cocos2dx ScrollView 测试一 触摸事件优先级和自动调整
查看>>
django 使用mysql数据库的流程
查看>>
Android系统移植与调试之------->如何修改Android设备的默认休眠时间
查看>>
我的Android进阶之旅------>Java文件大小转换工具类 (B,KB,MB,GB,TB,PB之间的大小转换)...
查看>>