java操作Elasticsearch 动态创建自定义空间索引 geo_shape 批量更新数据

1 篇文章 0 订阅
1 篇文章 0 订阅

由于数据未知,所以无法使用bean的方式,只能使用map来操作。

首先创建客户端

import java.net.InetAddress;
import java.net.UnknownHostException;

import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.transport.client.PreBuiltTransportClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyESConfig {

    @Bean
    public TransportClient client() throws UnknownHostException {
        TransportAddress node=new TransportAddress(InetAddress.getByName("127.0.0.1“), 9300);
        Settings setting=Settings.builder()
                .put("cluster.name","my-application")
                .build();
        TransportClient client=new PreBuiltTransportClient(setting);
        client.addTransportAddress(node);
        return client;
    }
}

WKT工具类

import com.vividsolutions.jts.geom.*;
import com.vividsolutions.jts.io.ParseException;
import com.vividsolutions.jts.io.WKTReader;
import org.geotools.geometry.jts.JTSFactoryFinder;

public class WKTUtil {
 
    private final static WKTReader wktReader = new WKTReader(JTSFactoryFinder.getGeometryFactory());
 
    /**
     * 将WKT文本字符串转换为ES中的GeoShape字符串格式
     * @param wkt
     * @return
     * @throws ParseException
     */
    public static String getESGeoTextFromWkt(String wkt) throws ParseException {
        String result = null;
        Geometry geom = wktReader.read(wkt);
        String type = geom.getClass().getSimpleName().toLowerCase();
        Point point;
        MultiPoint multiPoint;
        LineString lineString;
        MultiLineString multiLineString;
        Polygon polygon;
        MultiPolygon multiPolygon;
        if(type.equals("point")){
            point = (Point) geom;
            result = getESPointText(point);
        }else if(type.equals("linestring")){
            lineString = (LineString) geom;
            result = getESLineStringText(lineString);
        }else if(type.equals("polygon")){
            polygon = (Polygon) geom;
            result = getESPolygonText(polygon);
        }else if(type.equals("multipoint")){
            multiPoint = (MultiPoint) geom;
            result = getESMultiPointText(multiPoint);
        }else if(type.equals("multilinestring")){
            multiLineString = (MultiLineString) geom;
            result = getESMultiLineStringText(multiLineString);
        }else if(type.equals("multipolygon")){
            multiPolygon = (MultiPolygon) geom;
            result = getESMultiPolygonText(multiPolygon);
        }
        return result;
    }
 
    /**
     * 通过MultiPolygon对象拼接中括号表示的字符串
     * @param multiPolygon
     * @return
     */
    private static String getESMultiPolygonText(MultiPolygon multiPolygon) throws ParseException {
        Polygon polygon;
        int num = multiPolygon.getNumGeometries();
        StringBuffer sb = new StringBuffer("[");
        for(int i = 0; i < num; i++){
            polygon = (Polygon) multiPolygon.getGeometryN(i);
            sb.append(getESPolygonText(polygon)+",");
        }
        sb.setCharAt(sb.length() - 1, ']');
        return sb.toString();
    }
 
    /**
     * 通过MultiLineString对象拼接中括号表示的字符串
     * @param multiLineString
     * @return
     */
    private static String getESMultiLineStringText(MultiLineString multiLineString) {
        LineString lineString;
        int num = multiLineString.getNumGeometries();
        StringBuffer sb = new StringBuffer("[");
        for(int i = 0; i < num; i++){
            lineString = (LineString) multiLineString.getGeometryN(i);
            sb.append(getESLineStringText(lineString)+",");
        }
        sb.setCharAt(sb.length() - 1, ']');
        return sb.toString();
    }
 
    /**
     * 通过MultiPoint对象拼接中括号表示的字符串
     * @param multiPoint
     * @return
     */
    private static String getESMultiPointText(MultiPoint multiPoint) {
        Point point;
        int num = multiPoint.getNumGeometries();
        StringBuffer sb = new StringBuffer("[");
        for(int i = 0; i < num; i++){
            point = (Point) multiPoint.getGeometryN(i);
            sb.append(getESPointText(point)+",");
        }
        sb.setCharAt(sb.length() - 1, ']');
        return sb.toString();
    }
 
    /**
     * 通过Polygon对象拼接中括号表示的字符串
     * @param polygon
     * @return
     * @throws ParseException
     */
    private static String getESPolygonText(Polygon polygon){
        String result;
        /**
         * 内部闭合环形的数量
         */
        int num = polygon.getNumInteriorRing();
        if(num > 0){
            StringBuffer sb = new StringBuffer("["+getESLineStringText(polygon.getExteriorRing())+",");
            for(int i = 0; i < num; i++){
                sb.append(getESLineStringText(polygon.getInteriorRingN(i))+",");
            }
            sb.setCharAt(sb.length() - 1, ']');
            result = sb.toString();
        }else{
            result = "["+getESLineStringText(polygon.getExteriorRing())+"]";
        }
        return result;
    }
 
    /**
     * 通过LineString对象拼接中括号表示的字符串
     * @param lineString
     * @return
     */
    public static String getESLineStringText(LineString lineString){
        Coordinate[] corrds = lineString.getCoordinates();
        StringBuffer sb = new StringBuffer("[");
        for(Coordinate corrd : corrds) {
            sb.append(getCoordinateText(corrd)+",");
        }
        sb.setCharAt(sb.length() - 1, ']');
        return sb.toString();
    }
 
    /**
     * 通过Point对象拼接中括号表示的字符串
     * @param point
     * @return
     */
    public static String getESPointText(Point point){
        return getCoordinateText(point.getCoordinate());
    }
 
    /**
     * 通过Coordinate对象拼接中括号表示的字符串
     * @param coord
     * @return
     */
    public static String getCoordinateText(Coordinate coord) {
        return "["+coord.x+","+coord.y+"]";
    }
     
}

ES工具类

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsRequest;
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsResponse;
import org.elasticsearch.client.AdminClient;
import org.elasticsearch.client.IndicesAdminClient;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.io.ParseException;
import com.vividsolutions.jts.io.WKTReader;

public class ESUtil {

	/**
	 * 获取mapping
	 * @param map
	 * @param id
	 * @return
	 * @throws IOException
	 * @throws ParseException
	 */
	public static XContentBuilder getMapping(Map<String, Object> map, String id) throws IOException, ParseException {
		// 字段mapping
		XContentBuilder mapping = XContentFactory.jsonBuilder().startObject();

		mapping.field("id", id);
		// 几何类型
		if (map.get("wkt") != null) {
			String polygon = map.get("wkt").toString();
			mapping.field("wkt", getConversionData(polygon));
		}
		// 循环添加字段和值
		for (String key : map.keySet()) {
			// 排除要不需要的字段
			if (key.equals("indexName") || key.equals("id") || key.equals("wkt")) {
				continue;
			}
			mapping.field(key, map.get(key));
		}
		mapping.endObject();
		return mapping;
	}

	/**
	 * 获取json数据
	 * @param map
	 * @param id
	 * @return
	 * @throws ParseException
	 */
	public static String getJsonData(Map<String, Object> map, String id) throws ParseException {
		String json = "{";
		json += "\"id\":\"" + id + "\",";
		if (map.get("id") != null) {
			map.remove("id");
		}
		if (map.get("wkt") != null) {
			// wkt数据
			String wkt = map.get("wkt").toString();
			// wkt类型
			String geometry = wkt.substring(0, wkt.indexOf("(")).trim().toLowerCase();
			//ES能存储的格式
			String data = "{\"coordinates\":";
			data += WKTUtil.getESGeoTextFromWkt(wkt) + ",\"type\":\"" + geometry + "\"},";
			json += "\"wkt\":" + data;
			map.remove("wkt");
		}
		int i = 1;
		for (String key : map.keySet()) {
			json += "\"" + key + "\":\"" + map.get(key).toString() + "\"";
			if (i != map.size()) {
				json += ",";
			}
			i++;
		}
		json += "}";
		return json;
	}
	
	/**
	 * 获取转换数据
	 * @param wkt
	 * @return
	 * @throws ParseException
	 */
	private static Map<String,Object> getConversionData(String wkt) throws ParseException {
    	//空间数据类型
		String type=wkt.substring(0,wkt.indexOf("(")).trim().toLowerCase();

		Map<String,Object> map = new HashMap<String,Object>();
		map.put("type",type);
		WKTReader wktReader = new WKTReader();
		if(type.equals("point")){
			Point geoPoint =(Point) wktReader.read(wkt);
			Coordinate coordinates = geoPoint.getCoordinate();
			double[] point=new double[2];
			point[0]=coordinates.x;
			point[1]=coordinates.y;
			map.put("coordinates",point);
		}else if(type.equals("linestring")) {
			LineString geoLineString =(LineString) wktReader.read(wkt);
			Coordinate[] coordinates = geoLineString.getCoordinates();
			double[][] lineString = new double[coordinates.length][2];
			for(int i=0;i<coordinates.length;i++) {
				lineString[i][0] = coordinates[i].x;
				lineString[i][1] = coordinates[i].y;
			}
			map.put("coordinates",lineString);
		}else if(type.equals("polygon")||type.equals("multilinestring")) {
			/*Geometry geometry = wktReader.read(wkt);
			List<double[][]> list=new ArrayList<>();
			int length = geometry.getNumGeometries();
			for(int i=0;i<length;i++) {
				Geometry geometryN = geometry.getGeometryN(i);
				Coordinate[] coordinates = geometryN.getCoordinates();
				double[][] position = new double[coordinates.length][2];
				for(int j=0;j<coordinates.length;j++) {
					position[j][0]=coordinates[j].x;
					position[j][1]=coordinates[j].y;
				}
				list.add(position);
			}
			map.put("coordinates",list);*/
			//数据
			String data=wkt.trim().substring(wkt.indexOf("(")+1).trim();
			data=data.substring(0,data.length()-1).trim();
			String[] split = data.split("\\)");
			List<double[][]> list=new ArrayList<>();
			for(int i=0;i<split.length;i++) {
				String trim = split[i].replace("(", "").replace(")", "").trim();
				if((trim.charAt(0)+"").equals(",")) {
					trim=trim.substring(trim.indexOf(",")+1);
				}
				String[] split2 = trim.split(",");
				double[][] position = new double[split2.length][2];
				for(int j=0;j<split2.length;j++) {
					String ptstr = split2[j].trim();
					String[] lon_lat = ptstr.split(" ");
					position[j][0] = Double.parseDouble(lon_lat[0]);
					position[j][1] = Double.parseDouble(lon_lat[1]);
				}
				list.add(position);
			}
			map.put("coordinates",list);
		}else if(type.equals("multipolygon")){
			map=null;
		}else{
			map=null;
		}
		return map;
	}
	
	/**
	 * 创建索引库
	 * @param client 客户端
	 * @param idnexName 索引名称
	 * @param type 类型
	 * @return
	 * @throws Exception
	 */
    public static boolean createIndex(TransportClient client,String idnexName, String type) throws Exception {  
    	boolean sign=false;
    	try {
    		 // 创建mapping
            XContentBuilder mapping = XContentFactory.jsonBuilder()
                .startObject()
                    .startObject("properties")
                    .startObject("id").field("type", "text").endObject()
                    .startObject("wkt").field("type", "geo_shape").endObject().endObject()
                .endObject();

            AdminClient admin = client.admin();
            IndicesAdminClient indicesAdminClient = admin.indices();
            CreateIndexResponse createIndexResponse = indicesAdminClient.prepareCreate(idnexName)
                    .setSettings(Settings.builder()
                            .put("index.number_of_shards", 5)   // 分片
                            .put("index.number_of_replicas", 1) // 副本
                    )
                    .addMapping(type, mapping) // mapping
                    .get();
            createIndexResponse.isAcknowledged();
            sign=true;
		} catch (Exception e) {
			e.getMessage();
		}
       return sign;
    }

    /**
     * 判断索引名称是否存在
     * @param client 客户端
     * @param indexName 索引名称
     * @return
     */
  	public static boolean isExistsIndex(TransportClient client,String indexName){
          IndicesExistsResponse  response = client.admin().indices()
          		.exists(new IndicesExistsRequest().indices(new String[]{indexName})).actionGet();
          return response.isExists();
  	}
	
}

在需要操作的类进行注入

@Autowired
private TransportClient  client;

 

批量插入方法,map要包含indexName和wkt数据

/**
	 * 添加集合索引
	 * @param list<map>
	 * @return
	 * @throws Exception 
	 */
	@RequestMapping(value="/addIndexs",method=RequestMethod.POST)
	@ResponseBody
	public ResultBean addIndexs(@RequestBody List<Map<String,Object>> list) throws Exception  {
		ResultBean result =new ResultBean();		
		try {
			//索引库名称和类型
			String indexName=list.get(0).get("indexName").toString();
			//判断索引是否存在,不存在就进行创建
			if(!ESUtil.isExistsIndex(client,indexName)) {
				ESUtil.createIndex(client,indexName,indexName);
			}			
			//批量请求生成器
			BulkRequestBuilder bulkRequest = client.prepareBulk();
			
			for(int i=0;i<list.size();i++) {
				//id
				String id=UUID.randomUUID().toString().replace("-", "");
				/*//字段mapping
				XContentBuilder mapping=getMapping(list.get(i),id);
				bulkRequest.add(client.prepareIndex(indexName, indexName,id).setSource(mapping));*/
				
				//字段json
				String json=ESUtil.getJsonData(list.get(i),id);
				bulkRequest.add(client.prepareIndex(indexName, indexName,id).setSource(json,XContentType.JSON));
				
				if(i==0) {
					continue;
				}
				if(i==list.size()-1) {
					bulkRequest.get();
					break;
				}
				if(i%2000==0) {
					bulkRequest.get();
					bulkRequest=client.prepareBulk();
				}
			}
			result.setCode(200);
			result.setMsg("插入成功");
		} catch (Exception e) {
			result.setCode(500);
			result.setMsg(e.getMessage());
		}
		return result;
	}

 

wkt数据

LINESTRING(104.06076431390831 30.66749572727531,104.06728744623253 30.66776275637494)
LINESTRING(104.06133651762504 30.66513061547994,104.06744003354108 30.66520690782454)
LINESTRING(104.06133651762504 30.662803649202033,104.06736374250615 30.663337707401297)
LINESTRING(104.06232833774995 30.660285949443278,104.06763076898643 30.660781860815405)

POLYGON((104.057874680002 30.65196990964523,104.0613269802998 30.6519889830588,104.05997276335258 30.64998626644865,104.057874680002 30.65196990964523))

MULTILINESTRING ((104.043827058631 30.64563751310743,104.04817581133102 30.640754698279125),(104.04817581133102 30.640754698279125,104.08449173090048 30.641326901995853))

POINT(104.12048340775073 30.710449228936344)
POINT(103.97399900481105 30.79467767471215)

 

 

 

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值