ElasticSearch2.1 基于空间位置geo_query距离计算
2016-03-15 14:49
671 查看
首先声明 我使用的ES版本是2.1,不同版本api可能不尽相同
1、首先创建索引mapping
(1)方法1
4、写main方法测试
1、首先创建索引mapping
(1)方法1
// 创建索引方法1 public static void createIndex2(String indexName, String indexType) throws IOException { Settings settings = Settings.settingsBuilder() .put("cluster.name", "cluster_wubing") .build(); InetAddress inetAddress = InetAddress.getByName("192.168.1.107");; Client esClient = TransportClient.builder().settings(settings).build() .addTransportAddress(new InetSocketTransportAddress(inetAddress, 9300)); //创建mapping,我这里使用的分词器analyzer/search_analyzer为ik,注意位置location类型为geo_point String mapping = "{\"properties\": {\n" + " \"id\": {\n" + " \"type\": \"integer\",\n" + " \"index\": \"not_analyzed\",\n" + " \"include_in_all\": false\n" + " },\n" + " \"title\": {\n" + " \"type\": \"string\",\n" + " \"store\": \"no\",\n" + " \"term_vector\": \"with_positions_offsets\",\n" + " \"analyzer\": \"ik_max_word\",\n" + " \"search_analyzer\": \"ik_max_word\",\n" + " \"include_in_all\": true\n" + " },\n" + " \"city\": {\n" + " \"type\": \"string\",\n" + " \"store\": \"no\",\n" + " \"term_vector\": \"with_positions_offsets\",\n" + " \"analyzer\": \"ik_max_word\",\n" + " \"search_analyzer\": \"ik_max_word\",\n" + " \"include_in_all\": true\n" + " },\n" + " \"location\":{\n" + " \"type\":\"geo_point\",\n" + " \"index\": \"not_analyzed\",\n" + " \"include_in_all\": false\n" + " }\n" + " }}"; esClient.admin().indices().prepareCreate(indexName).execute().actionGet(); PutMappingResponse response = esClient.admin().indices().preparePutMapping(indexName) .setType(indexType) .setSource(mapping) .get(); 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."); } }2.方法2此方法mapping易读。City类自己创建
// 创建索引 public static void createIndex(String indexName, String indexType) throws IOException { Settings settings = Settings.settingsBuilder() .put("cluster.name", "cluster_wubing") .build(); InetAddress inetAddress = InetAddress.getByName("192.168.1.107");; Client esClient = TransportClient.builder().settings(settings).build() .addTransportAddress(new InetSocketTransportAddress(inetAddress, 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("city").field("type", "string").endObject() // 位置 .startObject("location").field("type", "geo_point").endObject() // 标题 .startObject("title").field("type", "string").endObject() .endObject().endObject().endObject(); } catch (IOException e) { e.printStackTrace(); } return mapping; }2、向索引里添加数据
// 添加数据 public static Integer addIndexData(String indexName, String indexType) throws Exception { Client client = ElasticSerachUtil.getClient(); List<String> cityList = new ArrayList<String>(); City city1 = new City(1L, "北京", 116.395645, 39.929986, "中国人民站起来了,北京人民可以天天站在天安门广场吃烤鸭了"); City city2 = new City(2L, "天津", 117.210813, 39.143931, "中国人民站起来了,天津人民可以天天在迎宾广场吃麻花了"); City city3 = new City(3L, "青岛", 120.384428, 36.105215, "中国人民站起来了,青岛人民可以天天在!最后一次,不要错过今天"); City city4 = new City(4L, "哈尔滨", 126.657717, 45.773225, "中国人民站起来了,哈尔滨人民可以天天站在索菲亚广场吃红肠了"); City city5 = new City(5L, "乌鲁木齐", 87.564988, 43.840381, "中国人民站起来了,乌鲁木齐人民可以天天在人民广场啃羊腿了"); City city6 = new City(6L, "三亚", 109.522771, 18.257776, "中国人民站起来了,三亚人民可以让青岛政府去丢吧,让他们创城去吧!"); cityList.add(obj2JsonUserData(city1)); cityList.add(obj2JsonUserData(city2)); cityList.add(obj2JsonUserData(city3)); cityList.add(obj2JsonUserData(city4)); cityList.add(obj2JsonUserData(city5)); cityList.add(obj2JsonUserData(city6)); // 创建索引库 List<IndexRequest> requests = new ArrayList<IndexRequest>(); 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(City city) { String jsonData = null; try { // 使用XContentBuilder创建json数据 XContentBuilder jsonBuild = XContentFactory.jsonBuilder(); jsonBuild.startObject().field("id", city.getId()) .field("city", city.getCity()) //注意纬度在前,经度在后 location类型 .startArray("location").value(city.getLat()).value(city.getLon()).endArray() .field("title", city.getTitle()) .endObject(); jsonData = jsonBuild.string(); System.out.println(jsonData); } catch (IOException e) { e.printStackTrace(); } return jsonData; }3、最后创建search搜索和距离计算
// 模糊查询 public static void query(String query) throws Exception { Client client = ElasticSerachUtil.getClient(); QueryStringQueryBuilder qsqb = new QueryStringQueryBuilder(query); // qsqb.analyzer("ik").field("title"); qsqb.field("title"); client.admin().indices().prepareRefresh().execute().actionGet(); SearchResponse searchResponse = client.prepareSearch("testes").setTypes("xq").setQuery(qsqb) // .setScroll(new TimeValue(60000)) .addFields("id", "title", "updatetime") // .addSort("updatetime", SortOrder.DESC) .addSort("_score", SortOrder.DESC) // .addHighlightedField("title") .setHighlighterEncoder("UTF-8").execute().actionGet(); // 搜索耗时 Float usetime = searchResponse.getTookInMillis() / 1000f; // 命中记录数 Long hits = searchResponse.getHits().totalHits(); System.out.println("查询到记录数=" + hits); for (SearchHit hit : searchResponse.getHits()) { // 打分 Float score = hit.getScore(); Integer id = Integer.parseInt(hit.getFields().get("id").value().toString()); String title = hit.getFields().get("title").value().toString(); System.out.println(title); } } // 获取附近的城市 public static void testGetNearbyCities(Client client, String index, String type, double lat, double lon) throws ExecutionException, InterruptedException { SearchRequestBuilder srb = client.prepareSearch(index).setTypes(type); // srb.setPos // wx4g0th9p0gk 为北京的geohash 范围为lt(小于) 1500km内的数据 QueryBuilder builder = geoDistanceRangeQuery("location") .point(lat,lon)//注意纬度在前,经度在后 .from("0km") .to("10000km") .includeLower(true) .includeUpper(false) .optimizeBbox("memory") .geoDistance(GeoDistance.ARC); srb.setQuery(builder); // 获取距离多少公里 这个才是获取点与点之间的距离的 //GeoDistanceSortBuilder sort = SortBuilders.geoDistanceSort("location"); GeoDistanceSortBuilder sort = new GeoDistanceSortBuilder("location"); sort.unit(DistanceUnit.KILOMETERS);//距离单位公里 sort.order(SortOrder.ASC); sort.point(lat,lon);//注意纬度在前,经度在后 srb.addSort(sort); SearchResponse searchResponse = srb.execute().actionGet(); SearchHits hits = searchResponse.getHits(); SearchHit[] searchHists = hits.getHits(); System.out.println("北京附近的城市(" + hits.getTotalHits() + "个):"); for (SearchHit hit : searchHists) { String city = (String) hit.getSource().get("city"); String title = (String) hit.getSource().get("title"); // 获取距离值,并保留两位小数点 BigDecimal geoDis = new BigDecimal((Double) hit.getSortValues()[0]); Map<String, Object> hitMap = hit.getSource(); // 在创建MAPPING的时候,属性名的不可为geoDistance。 hitMap.put("geoDistance", geoDis.setScale(2, BigDecimal.ROUND_HALF_DOWN)); System.out.println(city + "距离北京" + hit.getSource().get("geoDistance") + DistanceUnit.KILOMETERS.toString() + "---" + title); } }
4、写main方法测试
public static void main(String[] args) throws Exception { Settings settings = Settings.settingsBuilder() .put("cluster.name", "cluster_wubing") .build(); InetAddress inetAddress = InetAddress.getByName("192.168.1.107");; Client client = TransportClient.builder().settings(settings).build() .addTransportAddress(new InetSocketTransportAddress(inetAddress, 9300)); String index = "testes2"; String type = "xq2"; //createIndex2(index, type); //addIndexData(index, type); double lat = 39.929986; double lon = 116.395645; long start = System.currentTimeMillis(); testGetNearbyCities(client, index, type, lat, lon); query("政府"); long end = System.currentTimeMillis(); System.out.println((end - start) + "毫秒"); client.close(); }搜索结果
相关文章推荐
- iOS边练边学--UITableView性能优化之三种方式循环利用
- 向ArcSDE导入数据出现(ORA-00001: Unique contraint (SDE.GDB_OC_PKC) violated错误
- UIPasteboard 粘贴板
- 关于UIUICollectionView
- easyui-tabs第一个标签被遮挡
- UIPageViewController
- UITableView的Grouped模式下,tableHeaderView与第一个section之间的空隙变大问题
- Easyui datagrid 分页参数自定义名称+额外参数
- UILabel各种属性设置
- 让 UIAlertController 兼容 iOS7
- UIView如何管理它的子视图
- LLDB 调试 UI 的技巧
- [DP 找规律] BZOJ2489 Random Sequence
- iOS NSOperation/Queue
- leetcode70.[DP] Climbing Stairs My Submissions Question
- 使用jquer获取当前时间,并赋值到input上。
- Handler消息机制实现更新主UI
- POJ2524 Ubiquitous Religions
- pip install -r requirements.txt 安装mysqldb失败 解决方案
- UIScrollView使用自动布局不能滑动的解决方法