前言

前面在elasticsearch中的geo_point 查询检索  中,我们大致了解在ES中geo数据是如何导入进行索引,以及进行区域范围查询的DSL语法。前面也讲过实际项目项目我们的geo数据是从数据库中导入到ES中进行索引,而且ES中的空间查询一般是结合地图来一起实现。所以这里利用logstash的jdbc配置来索引数据库中数据,在百度地图上实现鼠标点击之处,展示其附近的其他坐标点。

利用logstash来索引坐标数据

我们常说的ELK主要是用来做系统的日志分析等功能,这里面的L就是logstash。logstash就是将系统的日志导入到ES中进行索引,然后再利用kibana来做报表展示分析。而logstash不仅能处理日志文件,他的数据来源也可以是数据库,只需要配置jdbc形式,就可以将数据库中的数据定时导入到ES中进行索引。所以这里我们用logstash来抽取坐标数据,在ES索引方便后面在地图上展示,这里对于ELK和logstash,我们不着重讲解。下面是logstash的配置文件,来定时抽取数据库中的坐标数据。

input{
    stdin{

    }
    jdbc{
        #数据库连接配置
        jdbc_connection_string => "jdbc:oracle:************"
        jdbc_user => "admin"
        jdbc_password => "admin"
        jdbc_driver_library => "/opt/elk/logstash-5.6.11/lib/OracleDriver-5.0.jar" 
        jdbc_driver_class => "Java::oracle.jdbc.driver.OracleDriver"
        jdbc_paging_enabled => "true"
        jdbc_page_size => "500000" 
        statement => "select t.*  from table  t  " 
        # 各字段含义(由左至右)分、时、天、月、年,全部为*默认含义为每分钟都更新
        schedule => "6 * * * *"  
        type => "jdbc"  
    }

}
#这里的filter是重点,下面的jd,wd要和数据库字段对应,注意大小写
filter {
     mutate {
          add_field => ["[geoip][location]", "%{jd}"]
          add_field => ["[geoip][location]", "%{wd}"]
     }
     mutate {
          convert => ["[geoip][location]", "float"]
     }
 }
output{
    elasticsearch{
        hosts => "localhost:9200" # ES连接
        index => "logstash-dwjgjwd"      # ES索引名称
        document_id => "%{id}"   # id对应ORACLE中主键字段
    }
}

上面对于logstash中的input,filter,output。其实就是分别对应数据的输入,过滤,和输出。这里我们着重看一下filter,它将数据库中的,jd和wd添加到geoid的location数组中,然后再转化为float类型。因为这里我们没有在logstash中自定义mapping,我们用的就是ES自带的mapping,当然你也可以自己定义mapping,然后在logstash中进行引用。重点:对于使用ES自带的mapping,我们在logstash中定义索引名称的时候一定要定义为logstash-****这种形式。否则在建索引的时候location中是没有数据的。

索引建好之后,我们可以在kibana中进行范围区域查询,(顺带检验坐标数据是否已经正确索引)可以用下面的语句来进行查询

GET logstash-dwjgjwd/_search
{ 
  "from":0,
  "size":50,
  "query": {
    "geo_distance": {
      "distance": "1800m",
      "geoip.location":[118.32,32.30]
    }
  }
}

在百度地图上进行展示

上面坐标数据已经索引好了,接下来就是根据坐标数据在地图上进行标注了,至于具体如果调用ES的接口来查询数据这里不作重点。对于百度地图运用由于篇幅问题也不详细讲解,有兴趣的可以自行百度哈。主要的js脚本如下

//地图上监听鼠标的click事件
        map.addEventListener("click",function(e){
        	//鼠标点击当前范围标注点之前,清除之前标注的点
        	map.clearOverlays();
    		var markers = [];
        	var pt = null;
        	var paraJson={
      			  "from":0,
      			  "size":80,
          		  "query": {
          			    "geo_distance": {
          			    "distance": "400m",
          			    "geoip.location":[e.point.lng,e.point.lat]
          			   }
          	           }
          		};
            $.ajax({
                url:"http://"+requestIp+"/logstash-dwjgjwd/_search",
                data:JSON.stringify(paraJson),
	        type:"post",
		contentType:'application/json',
		dataType:'json',
                success:function(jsonData){
                	// 编写自定义函数,创建标注
                	function addMarker(point,label){
                	  var marker = new BMap.Marker(point);
                	  marker.setLabel(setLabelStyle(label));
                	  map.addOverlay(marker);
                	}
                	$.each(jsonData.hits.hits,function(index,array){
             	 	   pt = new BMap.Point(array._source.geoip.location[0],
                           array._source.geoip.location[1]);
             	 	   addMarker(pt,array._source.dwmc);
             	 	}); 
               	},error:function() {
                   alert("查询数据失败!");
               }
           });
    	});

上面用到的setLabelStyle()方法如下

/**
 *  在地图标注上设置label标签
 */
function setLabelStyle(content) { 
	//左偏移  右偏移
	var offsetSize = new BMap.Size(0, 0); 
	var labelStyle = {
	color: "#50c414", 
	backgroundColor: "#333333", 
	border: "0", 
	fontSize : "14px", 
	opacity:"0.8", 
	verticalAlign:"center", 
	borderRadius: "2px", 
	whiteSpace:"normal", 
	wordWrap:"break-word", 
	padding:"7px", 
	};
	//用于设置样式 
	var spanA="<span class='angle'><span>" ;
	//不同数字长度需要设置不同的样式。
	var num=parseInt(content.length/10) ;
	switch(num){ 
	case 0: 
	offsetSize = new BMap.Size(-20, -40);
		break;
	case 1:
	offsetSize = new BMap.Size(-20, -40);
		break;
	case 2: 
	offsetSize = new BMap.Size(-20, -60); 
		break; 
	case 3: 
	offsetSize = new BMap.Size(-20, -80); 
	        break; 
	default:
		break; 
	} 
	var label = new BMap.Label(content+spanA, { offset: offsetSize }); 
	label.setStyle(labelStyle);
	return label; 
}

<span class='angle'><span>的样式如下

.angle{
	display: inline-block;
	width: 0px;
	height: 0px;
	position: absolute;
	bottom:-60px;
	border: 14px solid;
	left: 15px;
	bottom: -25px;
	opacity: 0.8;
	border-color: #333333 transparent transparent transparent;
}

实现效果如下

es如何实现group by es如何实现范围查询_数据