前言
前面在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;
}
实现效果如下