GVKun编程网logo

laravel inopt框定位地理位置(laravel框架怎么用)

21

在本文中,我们将带你了解laravelinopt框定位地理位置在这篇文章中,我们将为您详细介绍laravelinopt框定位地理位置的方方面面,并解答laravel框架怎么用常见的疑惑,同时我们还将给

在本文中,我们将带你了解laravel inopt框定位地理位置在这篇文章中,我们将为您详细介绍laravel inopt框定位地理位置的方方面面,并解答laravel框架怎么用常见的疑惑,同时我们还将给您一些技巧,以帮助您实现更有效的AngularJS进阶 二十 HTML5实现获取地理位置信息并定位功能、AngularJS进阶(二十)HTML5实现获取地理位置信息并定位功能、elasticsearch 地理位置查询、Elasticsearch地理位置总结

本文目录一览:

laravel inopt框定位地理位置(laravel框架怎么用)

laravel inopt框定位地理位置(laravel框架怎么用)

    <div>
        <label>地址</label>
        <div>
            <input type="text" name="address"  id="address" placeholder="请输入" autocomplete="off" onclick="map()">
        </div>
    </div>
<script type="text/javascript">
    function map() {
        $.ajax({
            type: "get",//接口规定,只能用get
            async: true,//异步
            url: "https://apis.map.qq.com/ws/location/v1/ip",//接口地址
            data: {"key": "腾讯地图的key", "output": "jsonp"},//参数格式必须用到output传参为jsonp,否则会报跨域问题
            dataType: "jsonp",//跨域,必须用到jsonp
            success: function (result) {
                // console.log(result.message)  ;
                // console.log(result.result.ad_info)  ;
                //    进行追加至input
                $('#address').val(result.result.ad_info.nation+'/'+result.result.ad_info.province+'/'+result.result.ad_info.city)
            },
            error: function (XMLHttpRequest, textStatus, errorThrown) {
                console.log(JSON.stringify(XMLHttpRequest));
                document.write(JSON.stringify(XMLHttpRequest));
            }
        });
    }

</script>

获取腾讯地图的key

https://lbs.qq.com/dev/console/application/mine

效果图

 

AngularJS进阶 二十 HTML5实现获取地理位置信息并定位功能

AngularJS进阶 二十 HTML5实现获取地理位置信息并定位功能

HTML5实现获取地理位置信息并定位功能

注:请点击此处进行充电!

前言

     这篇文章主要介绍了HTML5实现获取地理位置信息并定位功能,本文讲解了原生HTML5、百度地图、谷歌地图等三种获取理位置信息并定位的方法,需要的朋友可以参考下

HTML5提供了地理位置定位功能(Geolocation API),能确定用户位置,我们可以借助HTML5的该特性开发基于地理位置信息的应用。本文结合实例给大家分享如何使用HTML5,借助百度、谷歌地图接口来获取用户准确的地理位置信息。

如何使用HTML5地理位置定位功能

      定位功能(Geolocation)是HTML5的新特性,因此只有在支持HTML5的现代浏览器上运行,特别是手持设备如iphone,地理定位更加精确。首先我们要检测用户设备浏览器是否支持地理定位,如果支持则获取地理信息。注意这个特性可能侵犯用户的隐私,除非用户同意,否则用户位置信息是不可用的,所以我们在访问该应用时会提示是否允许地理定位,我们当然选择允许即可。

 

function getLocation(){ 
if (navigator.geolocation){ 
navigator.geolocation.getCurrentPosition(showPosition,showError); 
}else{ 
alert("浏览器不支持地理定位。"); 
} 
}

 

      从上面的代码可以知道,如果用户设备支持地理定位,则运行 getCurrentPosition() 方法。如果getCurrentPosition()运行成功,则向参数showPosition中规定的函数返回一个coordinates对象,getCurrentPosition() 方法的第二个参数showError用于处理错误,它规定当获取用户位置失败时运行的函数。

      我们先来看函数showError(),它规定获取用户地理位置失败时的一些错误代码处理方式:

 

function showError(error){ 
switch(error.code) { 
case error.PERMISSION_DENIED: 
alert("定位失败,用户拒绝请求地理定位"); 
break; 
case error.POSITION_UNAVAILABLE: 
alert("定位失败,位置信息是不可用"); 
break; 
case error.TIMEOUT: 
alert("定位失败,请求获取用户位置超时"); 
break; 
case error.UNKNowN_ERROR: 
alert("定位失败,定位系统失效"); 
break; 
} 
}

 

我们再来看函数showPosition(),调用coordslatitudelongitude即可获取到用户的纬度和经度。

 

function showPosition(position){ 
var lat = position.coords.latitude; //纬度 
var lag = position.coords.longitude; //经度 
alert(‘纬度:‘+lat+‘,经度:‘+lag); 
}

 

利用百度地图和谷歌地图接口获取用户地址

      上面我们了解了HTML5Geolocation可以获取用户的经纬度,那么我们要做的是需要把抽象的经纬度转成可读的有意义的真正的用户地理位置信息。幸运的是百度地图和谷歌地图等提供了这方面的接口,我们只需要将HTML5获取到的经纬度信息传给地图接口,则会返回用户所在的地理位置,包括省市区信息,甚至有街道、门牌号等详细的地理位置信息。

      我们首先在页面定义要展示地理位置的元素,分别定义id#baidu_geoid#google_geo。我们只需修改关键函数showPosition()

  先来看百度地图接口交互,我们将经纬度信息通过Ajax方式发送给百度地图接口,接口会返回相应的省市区街道信息。百度地图接口返回的是一串JSON数据,我们可以根据需求将需要的信息展示给#baidu_geo。注意这里用到了jQuery库,需要先加载jQuery库文件。

 

function showPosition(position){ 
var latlon = position.coords.latitude+‘,‘+position.coords.longitude; 
//baidu 
var url = " <ahref="http://api.map.baidu.com/geocoder/v2/?ak=C93b5178d7a8ebdb830b9b557abce78b&callback=renderReverse&location="+latlon+"&output=json&pois=0</a>"; 
$.ajax({ 
type: "GET",dataType: "jsonp",url: url,beforeSend: function(){ 
$("#baidu_geo").html(‘正在定位...‘); 
},success: function (json) { 
if(json.status==0){ 
$("#baidu_geo").html(json.result.formatted_address); 
} 
},error: function (XMLHttpRequest,textStatus,errorThrown) { 
$("#baidu_geo").html(latlon+"地址位置获取失败"); 
} 
}); 
});

 

      再来看谷歌地图接口交互。同样我们将经纬度信息通过Ajax方式发送给谷歌地图接口,接口会返回相应的省市区街道详细信息。谷歌地图接口返回的也是一串JSON数据,这些JSON数据比百度地图接口返回的要更详细,我们可以根据需求将需要的信息展示给#google_geo

 

function showPosition(position){ 
var latlon = position.coords.latitude+‘,‘+position.coords.longitude; 
//google 
var url = ‘http://maps.google.cn/maps/api/geocode/json?latlng=‘+latlon+‘&language=CN‘; 
$.ajax({ 
type: "GET",beforeSend: function(){ 
$("#google_geo").html(‘正在定位...‘); 
},success: function (json) { 
if(json.status==‘OK‘){ 
var results = json.results; 
$.each(results,function(index,array){ 
if(index==0){ 
$("#google_geo").html(array[‘formatted_address‘]); 
} 
}); 
} 
},errorThrown) { 
$("#google_geo").html(latlon+"地址位置获取失败"); 
} 
}); 
}

 

      以上的代码分别将百度地图接口和谷歌地图接口整合到函数showPosition()中,我们可以根据实际情况进行调用。当然这只是一个简单的应用,我们可以根据这个简单的示例开发出很多复杂的应用,建议用手机浏览器访问DEMO演示。

美文美图

分享图片

分享图片

分享图片

再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!希望你也加入到我们人工智能的队伍中来!https://www.cnblogs.com/captainbed

AngularJS进阶(二十)HTML5实现获取地理位置信息并定位功能

AngularJS进阶(二十)HTML5实现获取地理位置信息并定位功能

HTML5实现获取地理位置信息并定位功能

注:请点击此处进行充电!

前言

     这篇文章主要介绍了HTML5实现获取地理位置信息并定位功能,本文讲解了原生HTML5、百度地图、谷歌地图等三种获取理位置信息并定位的方法,需要的朋友可以参考下。

HTML5提供了地理位置定位功能(Geolocation API),能确定用户位置,我们可以借助HTML5的该特性开发基于地理位置信息的应用。本文结合实例给大家分享如何使用HTML5,借助百度、谷歌地图接口来获取用户准确的地理位置信息。

如何使用HTML5地理位置定位功能

      定位功能(Geolocation)是HTML5的新特性,因此只有在支持HTML5的现代浏览器上运行,特别是手持设备如iphone,地理定位更加精确。首先我们要检测用户设备浏览器是否支持地理定位,如果支持则获取地理信息。注意这个特性可能侵犯用户的隐私,除非用户同意,否则用户位置信息是不可用的,所以我们在访问该应用时会提示是否允许地理定位,我们当然选择允许即可。

 

function getLocation(){ 
if (navigator.geolocation){ 
navigator.geolocation.getCurrentPosition(showPosition,showError); 
}else{ 
alert("浏览器不支持地理定位。"); 
} 
}

 

      从上面的代码可以知道,如果用户设备支持地理定位,则运行 getCurrentPosition() 方法。如果getCurrentPosition()运行成功,则向参数showPosition中规定的函数返回一个coordinates对象,getCurrentPosition() 方法的第二个参数showError用于处理错误,它规定当获取用户位置失败时运行的函数。

      我们先来看函数showError(),它规定获取用户地理位置失败时的一些错误代码处理方式:

 

function showError(error){ 
switch(error.code) { 
case error.PERMISSION_DENIED: 
alert("定位失败,用户拒绝请求地理定位"); 
break; 
case error.POSITION_UNAVAILABLE: 
alert("定位失败,位置信息是不可用"); 
break; 
case error.TIMEOUT: 
alert("定位失败,请求获取用户位置超时"); 
break; 
case error.UNKNowN_ERROR: 
alert("定位失败,定位系统失效"); 
break; 
} 
}

 

我们再来看函数showPosition(),调用coords的latitude和longitude即可获取到用户的纬度和经度。

 

function showPosition(position){ 
var lat = position.coords.latitude; //纬度 
var lag = position.coords.longitude; //经度 
alert('纬度:'+lat+',经度:'+lag); 
}

 

利用百度地图和谷歌地图接口获取用户地址

      上面我们了解了HTML5的Geolocation可以获取用户的经纬度,那么我们要做的是需要把抽象的经纬度转成可读的有意义的真正的用户地理位置信息。幸运的是百度地图和谷歌地图等提供了这方面的接口,我们只需要将HTML5获取到的经纬度信息传给地图接口,则会返回用户所在的地理位置,包括省市区信息,甚至有街道、门牌号等详细的地理位置信息。

      我们首先在页面定义要展示地理位置的元素,分别定义id#baidu_geo和id#google_geo。我们只需修改关键函数showPosition()。

  先来看百度地图接口交互,我们将经纬度信息通过Ajax方式发送给百度地图接口,接口会返回相应的省市区街道信息。百度地图接口返回的是一串JSON数据,我们可以根据需求将需要的信息展示给#baidu_geo。注意这里用到了jQuery库,需要先加载jQuery库文件。

 

 function showPosition(position){ 
var latlon = position.coords.latitude+','+position.coords.longitude; 
//baidu 
var url = "
<ahref="http://api.map.baidu.com/geocoder/v2/?ak=C93b5178d7a8ebdb830b9b557abce78b&callback=renderReverse&location="+latlon+"&output=json&pois=0</a>"; 
$.ajax({ 
type: "GET",dataType: "jsonp",url: url,beforeSend: function(){ 
$("#baidu_geo").html('正在定位...'); 
},success: function (json) { 
if(json.status==0){ 
$("#baidu_geo").html(json.result.formatted_address); 
} 
},error: function (XMLHttpRequest,textStatus,errorThrown) { 
$("#baidu_geo").html(latlon+"地址位置获取失败"); 
} 
}); 
});

 

      再来看谷歌地图接口交互。同样我们将经纬度信息通过Ajax方式发送给谷歌地图接口,接口会返回相应的省市区街道详细信息。谷歌地图接口返回的也是一串JSON数据,这些JSON数据比百度地图接口返回的要更详细,我们可以根据需求将需要的信息展示给#google_geo。

 

function showPosition(position){ 
var latlon = position.coords.latitude+','+position.coords.longitude; 
//google 
var url = 'http://maps.google.cn/maps/api/geocode/json?latlng='+latlon+'&language=CN'; 
$.ajax({ 
type: "GET",beforeSend: function(){ 
$("#google_geo").html('正在定位...'); 
},success: function (json) { 
if(json.status=='OK'){ 
var results = json.results; 
$.each(results,function(index,array){ 
if(index==0){ 
$("#google_geo").html(array['formatted_address']); 
} 
}); 
} 
},errorThrown) { 
$("#google_geo").html(latlon+"地址位置获取失败"); 
} 
}); 
}

 

      以上的代码分别将百度地图接口和谷歌地图接口整合到函数showPosition()中,我们可以根据实际情况进行调用。当然这只是一个简单的应用,我们可以根据这个简单的示例开发出很多复杂的应用,建议用手机浏览器访问DEMO演示。

美文美图

elasticsearch 地理位置查询

elasticsearch 地理位置查询

一、背景

最近有个需求,需要获取某个位置附近的楼盘,** 比如:** 获取当前用户所在位置,方圆 100km 千米之内的楼盘信息。经过调研,发现可以使用 redismongodbelasticsearch 等实现。经过考虑之后决定使用 es 来实现,此处简单记录下 esgeo 方面 api 的使用。

二、geo 数据类型

es 中存在 2 种地理位置数据类型,geo_pointgeo_shapees 无法自动识别这种数据类型,需要在创建 mapping 的时候,自己手动指定。

1、geo_point

geo_point 使用的是经纬度的坐标点,可以计算落在某个矩形内的点、以某个点为半径(圆)的点、某个多边形内的点(弃用了)、排序、聚合等操作。

geo_point

2、geo_shape

geo_shape 表示的是一个复杂的图形,使用的是 GeoJSON 的格式来表示复杂的图形。比如:我们要表示一个图书馆的坐标位置,如果图书馆占的位置比较大,用一个点表示可能就不准了,此时就可以使用 geo_shape 来表示了。

不过这种数据类型也有缺点:比如不能排序等等(因为是多边形的点)。

三、此处对 geo_point 类型实战

1、背景

image-20210421161252713

1、图中的 ① ② ③ ④ 表示是需要加入到 es 中的建筑物

建筑物 坐标 距离地点 相隔距离 解释
上海站 121.462311,31.256224 上海站    
上海静安洲际酒店 121.460186,31.251281 上海站 586.24 米 上海站和该酒店大概像个 586.24 米
交通公园 121.473939,31.253531 上海站 1146.45 米  
万业远景大厦 121.448215,31.26229 上海站 1501.74 米  

2、图中的圆形、正方形、多边形表示后期需要使用 es 查询出来里面里面的地点。

3、图中的短小的箭头➡️表示边界。

2、插入地点数据

1、创建索引

PUT /geo_index
{
  "settings": {
    "number_of_shards": 2,
    "number_of_replicas": 2,
    "analysis": {
      "analyzer": {
        "default": {
          "type": "ik_max_word"
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "building_name": {
        "type": "keyword"
      },
      "location": {
        // 此处手动指定数据类型
        "type": "geo_point"
      }
    }
  }
}
复制代码

注意⚠️:

1、在索引中,我们自己指定来 location 字段的类型为 geo_point 类型。

2、building_name 的字段类型为 keyword 表示不分词,这个字段只是为了测试,没有什么用。

3、不用指定索引的 type,在 es7 中只有一个 type。

2、插入地理位置数据

POST _bulk
{"create":{"_index":"geo_index","_id":1}}
{"building_name":"上海站","location":{"lat":31.256224,"lon":121.462311}}
{"create":{"_index":"geo_index","_id":2}}
{"building_name":"上海静安洲际酒店","location":"POINT (121.460186 31.251281)"}
{"create":{"_index":"geo_index","_id":3}}
{"building_name":"交通公园","location":"31.253531,121.473939"}
{"create":{"_index":"geo_index","_id":4}}
{"building_name":"万业远景大厦","location":[121.448215,31.26229]}
复制代码

注意⚠️:

1、从上面可知:地理位置的插入的格式可以存在 4种方式。

1、 {"lat":"","lon":""}
2、 "lat,lon"
3[Well-Known Text](https://docs.opengeospatial.org/is/12-063r5/12-063r5.html) "POINT (lon lat)"
4[lon,lat]
5、 还有一种 geohash 的格式

需要注意的是:使用 数组/Well-Known-Text 的格式的时候,经纬度是反过来的。
复制代码

3、执行检索

1、geo_bounding_box 矩形过滤

矩形位置大概坐标

从上图可知左上角和右下方的坐标分别为 (121.444075,31.265395) 和 (121.468417,31.253845)

执行查询,应该可以查询出 上海站万业远景大厦

1、es 查询语句

GET /geo_index/_search
{
  "query": {
    "bool": {
      "must": {
        "match_all": {}
      },
      "filter": {
        "geo_bounding_box": {
          "location": {
            "top_left": {
              "lat": 31.265395,
              "lon": 121.444075
            },
            "bottom_right": {
              "lat": 31.253845,
              "lon": 121.468417
            }
          }
        }
      }
    }
  }
}
复制代码

2、查询结果

矩形查询结果

从图中可以看到,查询出来了 上海站万业远景大厦,结果是正确的。

2、geo_distance 圆形查询

这个是距离查询,是以某个点向周围扩算的距离范围。

image-20210421161252713

在上一步的背景中,我们知道上海站的坐标 (121.462311,31.256224),同时也知道了上海站距离各个周边的距离有多远,此处我们以上海站为中心,查询方圆600米的建筑物,可知只有上海静安洲际酒店上海站符合。

1、es 查询语句

GET /geo_index/_search
{
  "query": {
    "bool": {
      "must": {
        "match_all": {}
      },
      "filter": {
        "geo_distance": {
          "distance": "600m",
          "distance_type": "arc", 
          "_name":"optional_name",
          "location": {
            "lat": 31.256224,
            "lon": 121.462311
          }
        }
      }
    }
  }
}
复制代码

注意⚠️:

1、distance_type 的值存在 2 个 arcplane

  • arc:默认的方式,这种方式计算比较精确,但是比较慢,是把地球当作一个球体计算。

  • plane:这种方式计算比较快,但是可能不怎么准,越靠近赤道越准,是把地球当成平坦的进行计算。

2、distance 后面可用的单位有 kmmcmmmnmimiydftin

image-20210421164716919

2、查询结果

距离查询

3、geo_distance 查询并排序,返回距离相隔多少米

1、es 查询语句

GET /geo_index/_search
{
  "query": {
    "bool": {
      "must": {
        "match_all": {}
      },
      "filter": {
        "geo_distance": {
          "distance": "600m",
          "distance_type": "arc",
          "_name": "optional_name",
          "location": {
            "lat": 31.256224,
            "lon": 121.462311
          }
        }
      }
    }
  },
  "sort": [
    {
      "_geo_distance": {
        "location": {
          "lat": 31.256224,
          "lon": 121.462311
        },
        "order": "desc",
        "unit": "m",
        "distance_type": "arc"
      }
    }
  ]
}
复制代码

注意⚠️:

1、sort 执行排序。

2、查询结果

距离排序

4、geo_distance 聚合

需求:

1. 统计`上海站`500米之内的建筑物有多少。
2. 统计`上海站`500-1000米之内的建筑物有多少。
3. 统计`上海站`大于1000米的建筑物有多少。
复制代码

1、es 查询语句

GET /geo_index/_search
{
  "query": {
    "bool": {
      "must": {
        "match_all": {}
      }
    }
  },
  "aggs": {
    "rings_around_amsterdam": {
      "geo_distance": {
        "field": "location",
        "origin": {
          "lat": 31.256224,
          "lon": 121.462311
        },
        "unit": "m",
        "distance_type": "arc",
        "ranges": [
          {"to": 500,"key": "first"},
          {"from": 500,"to": 1000,"key": "second" },
          {"from": 1000,"key": "third"}
        ],
        "keyed": true
      }
    }
  }
}
复制代码

2、查询结果

聚合

从上图中可以看到:

1、距离上海站在 0-500 米之间的建筑物只有 1 个。

2、距离上海站在 500-1000 之间的建筑物有 1 个。

3、距离上海站在 1000 以上的有 2 个。

5、geo-polygon - 多边形查询 (过时)

在 es7.12 中已经过时了,推荐使用 geo_shape 来实现

多边形查询过时了,推荐使用geo_shape查询

6、一个综合案例

1、需求:

1、查询语句 query,查询出所有的数据,并过滤出以上海站为中心的 3km 内的所有的建筑物。

2、aggs,用于统计出上海在 500 米以内、500-1000 米、1000 米之外的建筑物数量。

3、sort 用于排序。

4、post_filter 用于将结果缩小到上海站 1000 米以内。

2、查询结果

GET /geo_index/_search
{
  "query": {
    "bool": {
      "must": {
        "match_all": {}
      },
 // 过滤出上海站周围3km范围内的建筑物
      "filter": {
        "geo_distance": {
          "distance": "3km",
          "distance_type": "arc", 
          "_name":"optional_name",
          "location": {
            "lat": 31.256224,
            "lon": 121.462311
          }
        }
      }
    }
  },
 // 聚合上海站周围的建筑物的数量
  "aggs": {
    "rings_around_amsterdam": {
      "geo_distance": {
        "field": "location",
        "origin": {
          "lat": 31.256224,
          "lon": 121.462311
        },
        "unit": "m",
        "distance_type": "arc",
        "ranges": [
          {"to": 500,"key": "first"},
          {"from": 500,"to": 1000,"key": "second" },
          {"from": 1000,"key": "third"}
        ],
        "keyed": true
      }
    }
  },
// 对查询到的结果排序,并将距离放到响应数据的 sort 字段中。
  "sort": [
    {
      "_geo_distance": {
        "location": {
          "lat": 31.256224,
          "lon": 121.462311
        },
        "order": "desc",
        "unit": "m",
        "distance_type": "arc"
      }
    }
  ],
// 将结果缩小到上海站附近1km的范围内。
  "post_filter": {
    "geo_distance": {
      "distance": "1km",
      "location": {
        "lat": 31.256224,
        "lon": 121.462311
      }
    }
  }
}
复制代码

四、参考文档

1、geo_point 数据类型

2、距离单位

3、排序

4、矩形查询

5、圆形查询,距离查询

6、坐标拾取系统

 
作者:huan1993
链接:https://juejin.cn/post/6953547277172473892
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

Elasticsearch地理位置总结

Elasticsearch地理位置总结

更多内容请参考 : https://www.felayman.com 翻译版本:https://es.xiaoleilu.com/310_Geopoints/00_Intro.html 官方原文:https://www.elastic.co/guide/en/elasticsearch/guide/current/geoloc.html

本文只是针对这些内容通过具体的例子用java来实现其具体细节,如果只想看java实现部分,请直接往下面代码实现部分看

地理坐标点(geo-point) 是指地球表面可以用经纬度描述的一个点。地理坐标点可以用来计算两个坐标位置间的距离,或者判断一个点是否在一个区域中。地理坐标点不能被动态映射(dynamic mapping)自动检测,而是需要显式声明对应字段类型为 geo_point 。

PUT /attractions { "mappings": { "restaurant": { "properties": { "name": { "type": "string" }, "location": { "type": "geo_point" } } } } }

如上例,location 被声明为 geo_point 后,我们就可以索引包含了经纬度信息的文档了。经纬度信息的形式可以是字符串,数组或者对象。

PUT /attractions/restaurant/1 { "name": "Chipotle Mexican Grill", "location": "40.715, -74.011" <1> }

PUT /attractions/restaurant/2 { "name": "Pala Pizza", "location": { <2> "lat": 40.722, "lon": -73.989 } }

PUT /attractions/restaurant/3 { "name": "Mini Munchies Pizza", "location": [ -73.983, 40.719 ] <3> }

<1> 以半角逗号分割的字符串形式 “lat,lon”; <2> 明确以 lat 和 lon 作为属性的对象; <3> 数组形式表示 [lon,lat]。 注意 : 可能所有人都至少踩过一次这个坑:地理坐标点用字符串形式表示时是纬度在前,经度在后(”latitude,longitude”),而数组形式表示时刚好相反,是经度在前,纬度在后([longitude,latitude])。其实,在 Elasticesearch 内部,不管字符串形式还是数组形式,都是纬度在前,经度在后。不过早期为了适配 GeoJSON 的格式规范,调整了数组形式的表示方式。因此,在使用地理位置(geolocation)的路上就出现了这么一个“捕熊器”,专坑那些不了解这个陷阱的使用者。

通过地理坐标点过滤 有四种地理坐标点相关的过滤方式可以用来选中或者排除文档:

geo_bounding_box:: 找出落在指定矩形框中的坐标点 geo_distance:: 找出与指定位置在给定距离内的点 geo_distance_range:: 找出与指定点距离在给定最小距离和最大距离之间的点 geo_polygon:: 找出落在多边形中的点。这个过滤器使用代价很大。当你觉得自己需要使用它,最好先看看 geo-shapes 所有这些过滤器的工作方式都相似: 把 索引中所有文档(而不仅仅是查询中匹配到的部分文档,见 fielddata-intro)的经纬度信息都载入内存,然后每个过滤器执行一个轻量级的计算去判断当前点是否落在指定区域。 提示

地理坐标过滤器使用代价昂贵 —— 所以最好在文档集合尽可能少的场景使用。 你可以先使用那些简单快捷的过滤器,比如 term 或者 range,来过滤掉尽可能多的文档,最后才交给地理坐标过滤器处理。

布尔型过滤器(bool filter)会自动帮你做这件事。 它会优先让那些基于“bitset”的简单过滤器(见 filter-caching)来过滤掉尽可能多的文档,然后依次才是地理坐标过滤器或者脚本类的过滤器。

地理坐标盒模型过滤器 这是目前为止最有效的 地理坐标过滤器了,因为它计算起来非常简单。 你指定一个矩形的 顶部(top), 底部(bottom), 左边界(left), 和 右边界(right), 然后它只需判断坐标的经度是否在左右边界之间,纬度是否在上下边界之间。(译注:原文似乎写反了)

GET /attractions/restaurant/_search { "query": { "filtered": { "filter": { "geo_bounding_box": { "location": { <1> "top_left": { "lat": 40.8, "lon": -74.0 }, "bottom_right": { "lat": 40.7, "lon": -73.0 } } } } } } }

<1> 盒模型信息也可以用 bottom_left(左下方点)和 top_right(右上方点) 来表示。 优化盒模型 地理坐标盒模型过滤器不需要把所有坐标点都加载到内存里。 因为它要做的只是简单判断 纬度 和 经度 坐标数值是否在给定的范围内,所以它可以用倒排索引来做一个范围(range)过滤。 要使用这种优化方式,需要把 geo_point 字段用 纬度(lat)和经度(lon)方式表示并分别索引。

PUT /attractions { "mappings": { "restaurant": { "properties": { "name": { "type": "string" }, "location": { "type": "geo_point", "lat_lon": true <1> } } } } }

<1> location.lat 和 location.lon 字段将被分别索引。它们可以被用于检索,但是不会在检索结果中返回。 然后,查询时你需要告诉 Elasticesearch 使用已索引的 lat和lon。

GET /attractions/restaurant/_search { "query": { "filtered": { "filter": { "geo_bounding_box": { "type": "indexed", <1> "location": { "top_left": { "lat": 40.8, "lon": -74.0 }, "bottom_right": { "lat": 40.7, "lon": -73.0 } } } } } } }

<1> 设置 type 参数为 indexed (默认为 memory) 来明确告诉 Elasticsearch 对这个过滤器使用倒排索引。 注意:

geo_point 类型可以包含多个地理坐标点,但是针对经度纬度分别索引的这种优化方式(lat_lon)只对单个坐标点的方式有效。 地理距离过滤器 地理距离过滤器(geo_distance)以给定位置为圆心画一个圆,来找出那些位置落在其中的文档: GET /attractions/restaurant/_search { "query": { "filtered": { "filter": { "geo_distance": { "distance": "1km", <1> "location": { <2> "lat": 40.715, "lon": -73.988 } } } } } }

<1> 找出所有与指定点距离在1公里(1km)内的 location 字段。访问 Distance Units 查看所支持的距离表示单位

<2> 中心点可以表示为字符串,数组或者(如示例中的)对象。详见 lat-lon-formats。

地理距离过滤器计算代价昂贵。 为了优化性能,Elasticsearch 先画一个矩形框(边长为2倍距离)来围住整个圆形, 这样就可以用消耗较少的盒模型计算方式来排除掉那些不在盒子内(自然也不在圆形内)的文档, 然后只对落在盒模型内的这部分点用地理坐标计算方式处理。

提示 你需要判断你的使用场景,是否需要如此精确的使用圆模型来做距离过滤? 通常使用矩形模型是更高效的方式,并且往往也能满足应用需求。

更快的地理距离计算 两点间的距离计算,有多种性能换精度的算法:

arc:: 最慢但是最精确是弧形(arc)计算方式,这种方式把世界当作是球体来处理。 不过这种方式精度还是有限,因为这个世界并不是完全的球体。 plane:: 平面(plane)计算方式,(((“plane distance calculation”)))把地球当成是平坦的。 这种方式快一些但是精度略逊;在赤道附近位置精度最好,而靠近两极则变差。 sloppy_arc:: 如此命名,是因为它使用了 Lucene 的 SloppyMath 类。 这是一种用精度换取速度的计算方式,它使用 Haversine formula 来计算距离; 它比弧形(arc)计算方式快4~5倍, 并且距离精度达99.9%。这也是默认的计算方式。 你可以参考下例来指定不同的计算方式:

GET /attractions/restaurant/_search { "query": { "filtered": { "filter": { "geo_distance": { "distance": "1km", "distance_type": "plane", <1> "location": { "lat": 40.715, "lon": -73.988 } } } } } }

<1> 使用更快但精度稍差的平面(plane)计算方式。 提示: 你的用户真的会在意一个宾馆落在指定圆形区域数米之外了吗? 一些地理位置相关的应用会有较高的精度要求;但大部分实际应用场景中,使用精度较低但响应更快的计算方式可能就挺好。

地理距离区间过滤器 地理距离过滤器(geo_distance)和地理距离区间过滤器(geo_distance_range)的唯一差别在于后者是一个环状的,它会排除掉落在内圈中的那部分文档。

指定到中心点的距离也可以换一种表示方式: 指定一个最小距离(使用 gt或者gte)和最大距离(使用lt或者lte),就像使用区间(range)过滤器一样。

GET /attractions/restaurant/_search { "query": { "filtered": { "filter": { "geo_distance_range": { "gte": "1km", <1> "lt": "2km", <1> "location": { "lat": 40.715, "lon": -73.988 } } } } } }

匹配那些距离中心点超过1公里而小于2公里的位置。 缓存地理位置过滤器### 因为如下两个原因,地理位置过滤器默认是不被缓存的:

地理位置过滤器通常是用于查找用户当前位置附近的东西。但是用户是在移动的,并且没有两个用户的位置完全相同,因此缓存的过滤器基本不会被重复使用到。 过滤器是被缓存为比特位集合来表示段(segment)内的文档。假如我们的查询排除了几乎所有文档,只剩一个保存在这个特别的段内。一个未缓存的地理位置过滤器只需要检查这一个文档就行了,但是一个缓存的地理位置过滤器则需要检查所有在段内的文档。 缓存对于地理位置过滤器也可以很有效。 假设你的索引里包含了所有美国的宾馆。一个在纽约的用户是不会对旧金山的宾馆感兴趣的。 所以我们可以认为纽约是一个热点(hot spot),然后画一个边框把它和附近的区域围起来。

如果这个地理盒模型过滤器(geo_bounding_box)被缓存起来,那么当有位于纽约市的用户访问时它就可以被重复使用了。 它可以直接排除国内其它区域的宾馆。然后我们使用未缓存的,更加明确的地理盒模型过滤器(geo_bounding_box)或者地理距离过滤器(geo_distance)来在剩下的结果集中把范围进一步缩小到用户附近:

GET /attractions/restaurant/_search { "query": { "filtered": { "filter": { "bool": { "must": [ { "geo_bounding_box": { "type": "indexed", "_cache": true, <1> "location": { "top_left": { "lat": 40,8, "lon": -74.1 }, "bottom_right": { "lat": 40.4, "lon": -73.7 } } } }, { "geo_distance": { <2> "distance": "1km", "location": { "lat": 40.715, "lon": -73.988 } } } ] } } } } }

<1> 缓存的地理盒模型过滤器把结果集缩小到了纽约市。 <2> 代价更高的地理距离过滤器(geo_distance)让结果集缩小到1km内的用户。 减少内存占用 每一个 经纬度(lat/lon)组合需要占用16个字节的内存。要知道内存可是供不应求的。 使用这种占用16字节内存的方式可以得到非常精确的结果。不过就像之前提到的一样,实际应用中几乎都不需要这么精确。 你可以通过这种方式来减少内存使用量: 设置一个压缩的(compressed)数据字段格式并明确指定你的地理坐标点所需的精度。 即使只是将精度降低到1毫米(1mm)级别,也可以减少1/3的内存使用。 更实际的,将精度设置到3米(3m)内存占用可以减少62%,而设置到1公里(1km)则节省75%之多。

这个设置项可以通过 update-mapping API 来对实时索引进行调整:

POST /attractions/_mapping/restaurant { "location": { "type": "geo_point", "fielddata": { "format": "compressed", "precision": "1km" <1> } } }

<1> 每一个经纬度(lat/lon)组合现在只需要4个字节,而不是16个。 另外,你还可以这样做来避免把所有地理坐标点全部同时加载到内存中: 使用在优化盒模型(optimize-bounding-box)中提到的技术, 或者把地理坐标点当作文档值(doc values)来存储。

PUT /attractions { "mappings": { "restaurant": { "properties": { "name": { "type": "string" }, "location": { "type": "geo_point", "doc_values": true <1> } } } } }

<1> 地理坐标点现在不会被加载到内存,而是保存在磁盘中。 将地理坐标点映射为文档值的方式只能是在这个字段第一次被创建时。 相比使用字段值,使用文档值会有一些小的性能代价,不过考虑到它对内存的节省,这种方式通常是还值得的。

按距离排序 检索结果可以按跟指定点的距离排序:

提示 当你可以(can)按距离排序时,按距离打分(scoring-by-distance)通常是一个更好的解决方案。

GET /attractions/restaurant/_search { "query": { "filtered": { "filter": { "geo_bounding_box": { "type": "indexed", "location": { "top_left": { "lat": 40,8, "lon": -74.0 }, "bottom_right": { "lat": 40.4, "lon": -73.0 } } } } } }, "sort": [ { "_geo_distance": { "location": { <1> "lat": 40.715, "lon": -73.998 }, "order": "asc", "unit": "km", <2> "distance_type": "plane" <3> } } ] }

<1> 计算每个文档中 location 字段与指定的 lat/lon 点间的距离。 <2> 以 公里(km)为单位,将距离设置到每个返回结果的 sort 键中。 <3> 使用快速但精度略差的平面(plane)计算方式。 你可能想问:为什么要制定距离的单位(unit)呢? 用于排序的话,我们并不关心比较距离的尺度是英里,公里还是光年。 原因是,这个用于排序的值会设置在每个返回结果的 sort 元素中。

... "hits": [ { "_index": "attractions", "_type": "restaurant", "_id": "2", "_score": null, "_source": { "name": "New Malaysia", "location": { "lat": 40.715, "lon": -73.997 } }, "sort": [ 0.08425653647614346 <1> ] }, ...

<1> 宾馆距离我们的指定位置距离是 0.084km。 你可以通过设置单位(unit)来让返回值的形式跟你应用中想要的匹配。 提示 地理距离排序可以对多个坐标点来使用,不管(这些坐标点)是在文档中还是排序参数中。 使用 sort_mode 来指定是否需要使用位置集合的 最小(min),最大(max)或者平均(avg)距离。 这样就可以返回离我的工作地和家最近的朋友这样的结果了。

按距离打分 有可能距离只是决定返回结果排序的唯一重要因素,不过更常见的情况是距离会和其它因素, 比如全文检索匹配度,流行程度或者价格一起决定排序结果。

遇到这种场景你需要在查询分值计算(function_score query)中指定方式让我们把这些因子处理得到一个综合分。 decay-functions中有个一个例子就是地理距离影响排序得分的。

另外按距离排序还有个缺点就是性能:需要对每一个匹配到的文档都进行距离计算。 而 function_score请求,在 rescore phase阶段有可能只需要对前 n 个结果进行计算处理。

今天关于laravel inopt框定位地理位置laravel框架怎么用的讲解已经结束,谢谢您的阅读,如果想了解更多关于AngularJS进阶 二十 HTML5实现获取地理位置信息并定位功能、AngularJS进阶(二十)HTML5实现获取地理位置信息并定位功能、elasticsearch 地理位置查询、Elasticsearch地理位置总结的相关知识,请在本站搜索。

本文标签: