精华内容
下载资源
问答
  • redis-GEO地理位置

    万次阅读 2017-11-29 19:38:45
    Redis 3.2版本一个重大的更新是新增了GEO地理位置相关的命令。 目前Redis对地理位置支持提供了一下6个命令: 1. geoadd: 增加地理位置的坐标。2. geodist: 获取两个地理位置的距离。3. geohash: 获取地理...
    Redis 3.2版本一个重大的更新是新增了GEO地理位置相关的命令。
    目前Redis对地理位置支持提供了一下6个命令:
    1. 1. geoadd: 增加地理位置的坐标。
    2. 2. geodist: 获取两个地理位置的距离。
    3. 3. geohash: 获取地理位置的GeoHash值。
    4. 4. geopos: 获取地理位置的坐标。
    5. 5. georadius: 根据给定经纬度坐标获取指定范围内的地理位置集合。
    6. 6. georadiusbymember: 根据给定地理位置获取指定范围内的地理位置集合。

    GeoHash基本原理
    1. GeoHash是一种地址编码,通过切分地图区域为小方块(切分次数越多,精度越高),它能把二维的经纬度编码成一维的字符串。
    2. 也就是说,理论上geohash字符串表示的并不是一个点,而是一个矩形区域,只要矩形区域足够小,达到所需精度即可

    编码过程
    1. 以经纬度(116.390639.92324)为例:
    2. 1. 对于维度39.92324 39.92324属于(0, 90),所以取编码为1
    3. 然后再将(0, 90)分成 (0, 45), (45, 90)两个区间,而39.92324位于(0, 45),所以编码为0
    4. 以此类推,直到精度符合要求为止,得到纬度编码为1011 1000 1100 0111 1001
    5. 2. 经度也用同样的算法,对(-180, 180)依次细分,得到116.3906的编码为1101 0010 1100 0100 0100
    6. 3. 接下来将经度和纬度的编码合并,奇数位是纬度,偶数位是经度,得到编码 11100 11101 00100 01111 00000 01101 01011 00001
    7. 4. 最后,用0-9b-z(去掉a, i, l, o)这32个字母进行base32编码,得到(39.92324, 116.3906)的编码为wx4g0ec1
    8. 116.390639.92324)对应的地图位置就是http://geohash.org/wx4g0ec1,
    9. 降低一些精度,就会是http://geohash.org/wx4g0ec,
    10. 再降低一些精度,就会是http://geohash.org/wx4g0。
    编码特性
    1. 不难看出这样的编码方式仅用一个字符串保存经纬度信息,并且精度由字符串从头到尾的长度决定,编码长度越长,精度越高。
    2. GeoHash值的前缀相同的位数越多,代表的位置越接近,可以方便索引。(反之不成立,位置接近的GeoHash值不一定相似).
    3. 但这种方案的缺点是:从geohash的编码算法中可以看出,靠近每个方块边界两侧的点虽然十分接近,但所属的编码会完全不同
    4. 实际应用中,需要通过去搜索环绕当前方块周围的8个方块来解决该问题。
    5. 除此之外,这个方案也无法直接得到距离,需要程序协助进行后续的排序计算

    Redis Geo命令实现
    1. Redis将地理位置的52GeoHash值作为有序集合的score,将地理位置存放在有序集合中进行保存。
    2. 后续按位置搜索时,依据GeoHash的特性搜索当前方块与环绕当前方块的8个方块来搜索目标位置集合。

    1.GEOADD 
    1. 命令:GEOADD key longitude latitude member [longitude latitude member ...]
    2. 命令描述:将指定的地理空间位置(纬度、经度、名称)添加到指定的key
    3. 返回值:添加到sorted set元素的数目,但不包括已更新score的元素。
    1. Redis中接受的有效的精度范围为-180180度,有效维度范围为-85.05112878 85.05112878(靠近南北极的一小块地方是无法生成索引的)。
    • GEOADD  实现方式
    1. Redis内部使用有序集合来保存key,每一个memberscore大小为一个52位的Geohash值(double类型精度为52位)。
    2. 实际上Redis内部实现的时候就是将GEOADD命令转换成ZADD命令来实现的
    3. (这也解释了为什么没有专门的georem命令,地理位置信息是通过使用ZREM命令来删除成员。)

    2.GEODIST 
    1. 命令:GEODIST key member1 member2 [unit]
    2. 命令描述:
    3. 返回两个给定位置之间的距离。如果两个位置之间的其中一个不存在, 那么命令返回空值。指定单位的参数 unit 必须是以下单位的其中一个:
      • m 表示单位为米。
      • km 表示单位为千米。
      • mi 表示单位为英里。
      • ft 表示单位为英尺。
    • GEODIST 实现方式
    1. 使用WGS84坐标系统,计算距离时使用Haversine公式。由于地球并不是严格标准的,计算出来的距离有最大约0.5%的误差。


    3.GEOPOS 
    1. 命令:GEOPOS key member [member ...]
    2. 命令描述:key里返回所有给定位置元素的位置(经度和纬度)
    3. 返回值:GEOPOS 命令返回一个数组, 数组中的每个项都由两个元素组成: 
    4. 第一个元素为给定位置元素的经度, 而第二个元素则为给定位置元素的纬度。当给定的位置元素不存在时, 对应的数组项为空值。



    4.GEOHASH 
    1. 命令:GEOHASH key member [member ...]
    2. 命令描述:返回一个或多个位置元素的 Geohash 表示。通常使用表示位置的元素使用不同的技术,使用Geohash位置52点整数编码。
    3. 由于编码和解码过程中所使用的初始最小和最大坐标不同,编码的编码也不同于标准。此命令返回一个标准的Geohash
    4. 返回值:一个数组, 数组的每个项都是一个 geohash 命令返回的 geohash 的位置与用户给定的位置元素的位置一一对应。
    • GEOHASH 实现方式
    1. Redis在内部生成有序集合成员score时的geohash值与标准的算法略有差异(Redis内部使用-85,85作为维度范围,标准使用-90,90)。
    2. 这个命令返回的是标准值,与https://en.wikipedia.org/wiki/Geohash中标准算法和geohash.org网站的结果一致。

    5.GEORADIUS
    1. 命令:GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count]
    2. 命令描述:
    3. 以给定的经纬度为中心, 返回键包含的位置元素当中, 与中心的距离不超过给定最大距离的所有位置元素。
    4. 范围可以使用以下其中一个单位:
      1. m 表示单位为米。
      2. km 表示单位为千米。
      3. mi 表示单位为英里。
      4. ft 表示单位为英尺。
    5. 在给定以下可选项时, 命令会返回额外的信息:
      1. WITHDIST: 在返回位置元素的同时, 将位置元素与中心之间的距离也一并返回。 距离的单位和用户给定的范围单位保持一致。
      2. WITHCOORD: 将位置元素的经度和维度也一并返回。
      3. WITHHASH: 52 位有符号整数的形式, 返回位置元素经过原始 geohash 编码的有序集合分值。 这个选项主要用于底层应用或者调试, 实际中的作用并不大。
    6. 命令默认返回未排序的位置元素。 通过以下两个参数, 用户可以指定被返回位置元素的排序方式:
      1. ASC: 根据中心的位置, 按照从近到远的方式返回位置元素。
      2. DESC: 根据中心的位置, 按照从远到近的方式返回位置元素。
    7. 在默认情况下, GEORADIUS 命令会返回所有匹配的位置元素。 虽然用户可以使用 COUNT <count> 选项去获取前 N 个匹配元素, 但是因为命令在内部可能会需要对所有被匹配的元素进行处理, 所以在对一个非常大的区域进行搜索时, 即使只使用 COUNT 选项去获取少量元素, 命令的执行速度也可能会非常慢。 但是从另一方面来说, 使用 COUNT 选项去减少需要返回的元素数量, 对于减少带宽来说仍然是非常有用的。
    8. 返回值:
      1. 在没有给定任何 WITH 选项的情况下, 命令只会返回一个像 [“New York”,”Milan”,”Paris”] 这样的线性(linear)列表。
      2. 在指定了 WITHCOORD WITHDIST WITHHASH 等选项的情况下, 命令返回一个二层嵌套数组, 内层的每个子数组就表示一个元素。
        1. 在返回嵌套数组时, 子数组的第一个元素总是位置元素的名字。 至于额外的信息, 则会作为子数组的后续元素, 按照以下顺序被返回:
          1. 以浮点数格式返回的中心与位置元素之间的距离, 单位与用户指定范围时的单位一致。
          2. geohash 整数。
          3. 由两个元素组成的坐标,分别为经度和纬度。
    • GEORADIUS实现方式
    1. GeoHash值的前缀相同的位数越多,代表的位置越接近,可以方便索引。但反之不成立,位置接近的GeoHash值不一定相似。
    2. 靠近每个方块边界两侧的点虽然十分接近,但所属的编码会完全不同。实际应用中,需要通过去搜索环绕当前方块周围的8个方块来解决该问题。
    3. 搜索的时候会检查挡墙方块+8个覆盖整个搜索半径的区域,不断的去除geohash的低位,直到这9个方块能覆盖搜索半径位置。再一次搜索计算每个位置的距离。

    6.GEORADIUSBYMEMBER 
    1. 命令:GEORADIUSBYMEMBER key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count]
    2. 命令描述:这个命令和 GEORADIUS 命令一样, 都可以找出位于指定范围内的元素, 但是 GEORADIUSBYMEMBER 的中心点是由给定的位置元素决定的。



    展开全文
  • Elasticsearch 地理位置查询

    千次阅读 2019-06-26 19:44:18
    地理位置 我们拿着纸质地图漫步城市的日子一去不返了。得益于智能手机,我们现在总是可以知道自己所处的准确位置,也预料到网站会使用这些信息。我想知道从当前位置步行 5 分钟内可到的那些餐馆,对伦敦更大范围内的...

    本文参考自Elacticsearch的中文版翻译:https://es.xiaoleilu.com/
    并对基于Es 6.6.0版本进行API的更正。

    地理位置

    我们拿着纸质地图漫步城市的日子一去不返了。得益于智能手机,我们现在总是可以知道自己所处的准确位置,也预料到网站会使用这些信息。我想知道从当前位置步行 5 分钟内可到的那些餐馆,对伦敦更大范围内的其他餐馆并不感兴趣。

    但地理位置功能仅仅是 Elasticsearch 的冰山一角,Elasticsearch 的妙处在于,它让你可以把地理位置、全文搜索、结构化搜索和分析结合到一起。

    例如:告诉我提到 vitello tonnato 这种食物、步行 5 分钟内可到、且晚上 11 点还营业的餐厅,然后结合用户评价、距离、价格排序。另一个例子:给我展示一幅整个城市8月份可用假期出租物业的地图,并计算出每个区域的平均价格。

    Elasticsearch 提供了两种表示地理位置的方式:用纬度-经度表示的坐标点使用 geo_point 字段类型, 以 GeoJSON 格式定义的复杂地理形状,使用 geo_shape 字段类型。

    Geo-points 允许你找到距离另一个坐标点一定范围内的坐标点、计算出两点之间的距离来排序或进行相关性打分、或者聚合到显示在地图上的一个网格。另一方面,Geo-shapes 纯粹是用来过滤的。它们可以用来判断两个地理形状是否有重合或者某个地理形状是否完全包含了其他地理形状。

    地理坐标点

    地理坐标点(geo-point) 是指地球表面可以用经纬度描述的一个点。地理坐标点可以用来计算两个坐标位置间的距离,或者判断一个点是否在一个区域中。

    地理坐标点不能被动态映射(dynamic mapping)自动检测,而是需要显式声明对应字段类型为 geo_point。

    PUT /attractions
    {
      "mappings": {
        "restaurant": {
          "properties": {
            "name": {
              "type": "keyword"
            },
            "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::
      找出落在多边形中的点。这个过滤器使用代价很大。

    所有这些过滤器的工作方式都相似: 把索引中所有文档(而不仅仅是查询中匹配到的部分文档)的经纬度信息都载入内存,然后每个过滤器执行一个轻量级的计算去判断当前点是否落在指定区域。

    提示:
    地理坐标过滤器使用代价昂贵 —— 所以最好在文档集合尽可能少的场景使用。 你可以先使用那些简单快捷的过滤器,比如 term 或者 range,来过滤掉尽可能多的文档,最后才交给地理坐标过滤器处理。
    布尔型过滤器(bool filter)会自动帮你做这件事。 它会优先让那些基于“bitset”的简单过滤器(见 filter-caching)来过滤掉尽可能多的文档,然后依次才是地理坐标过滤器或者脚本类的过滤器。

    地理坐标盒模型过滤器

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

    GET /attractions/restaurant/_search
    {
      "query": {
        "bool": {
          "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": {
        "bool": {
          "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": {
        "bool": {
          "filter": {
            "geo_distance": {
              "distance": "1km", <1>
              "location": { <2>
                "lat":  40.715,
                "lon": -73.988
              }
            }
          }
        }
      }
    }
    
    • <1> 找出所有与指定点距离在1公里(1km)内的 location 字段。
    • <2> 中心点可以表示为字符串,数组或者(如示例中的)对象。

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

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

    更快的地理距离计算

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

    • arc::
      最慢但是最精确是弧形(arc)计算方式,这种方式把世界当作是球体来处理。 不过这种方式精度还是有限,因为这个世界并不是完全的球体。

    • plane::
      平面(plane)计算方式,(((“plane distance calculation”)))把地球当成是平坦的。 这种方式快一些但是精度略逊;在赤道附近位置精度最好,而靠近两极则变差。

    • sloppy_arc::
      如此命名,是因为它使用了 Lucene 的 SloppyMath 类。 这是一种用精度换取速度的计算方式,它使用 Haversine formula 来计算距离; 它比弧形(arc)计算方式快4~5倍, 并且距离精度达99.9%。这也是默认的计算方式。
      你可以参考下例来指定不同的计算方式:

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

    <1> 使用更快但精度稍差的平面(plane)计算方式。

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

    地理距离区间过滤器

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

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

    GET /attractions/restaurant/_search
    {
      "aggs": {
        "agg_by_distance_range": {
          "geo_distance": {
            "field": "location",
            "origin": {
              "lat": 40.715,
              "lon": -73.988
            },
            "unit": "km",
            "ranges": [
              {
                "from": 1, <1>
                "to": 2 <1>
              }
            ]
          }
        }
      }
    }
    

    <1> 匹配那些距离中心点超过1公里而小于2公里的位置。

    缓存地理位置过滤器

    因为如下两个原因,地理位置过滤器默认是不被缓存的:

    • 地理位置过滤器通常是用于查找用户当前位置附近的东西。但是用户是在移动的,并且没有两个用户的位置完全相同,因此缓存的过滤器基本不会被重复使用到。

    • 过滤器是被缓存为比特位集合来表示段(segment)内的文档。假如我们的查询排除了几乎所有文档,只剩一个保存在这个特别的段内。一个未缓存的地理位置过滤器只需要检查这一个文档就行了,但是一个缓存的地理位置过滤器则需要检查所有在段内的文档。

    缓存对于地理位置过滤器也可以很有效。 假设你的索引里包含了所有美国的宾馆。一个在纽约的用户是不会对旧金山的宾馆感兴趣的。 所以我们可以认为纽约是一个热点(hot spot),然后画一个边框把它和附近的区域围起来。
    如果这个地理盒模型过滤器(geo_bounding_box)被缓存起来,那么当有位于纽约市的用户访问时它就可以被重复使用了。 它可以直接排除国内其它区域的宾馆。然后我们使用未缓存的,更加明确的地理盒模型过滤器(geo_bounding_box)或者地理距离过滤器(geo_distance)来在剩下的结果集中把范围进一步缩小到用户附近:

    GET /attractions/restaurant/_search
    {
      "query": {
        "bool": {
          "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": "keyword"
            },
            "location": {
              "type":       "geo_point",
              "doc_values": true <1>
            }
          }
        }
      }
    }
    

    <1> 地理坐标点现在不会被加载到内存,而是保存在磁盘中。

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

    按距离排序

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

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

    GET /attractions/restaurant/_search
    {
      "query": {
        "bool": {
          "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 个结果进行计算处理。

    展开全文
  • Wireshark配置显示IP地理位置信息

    千次阅读 2019-12-26 20:34:45
    通过配置wireshark显示出IP地址蕴含的地理位置等信息

    本章跟大家介绍一下wireshark中IP地理位置信息配置的方法和原理,作为我的专栏《wireshark从入门到精通》中的一篇。

    在Wireshark中实用的设置和使用技巧汇总那一章节最后,我提到可以配置wireshark查看IP的地理位置等信息,如图1:
    在这里插入图片描述
    图1
    针对图1提出以下三个问题:

    • 如何配置wireshark进行地理位置的显示?
    • 可以看到有的地址是可以显示IP的地理位置信息,例如64.233.189.139,这样的IP被称之为非保留的IP地址。有的地址不可以显示地理位置信息,例如192.168.0.114,这样的IP被称之为保留IP。两者有什么区别呢?
    • AS number又是什么?

    如何配置wireshark进行地理位置的显示

    选择Wireshark 编辑->首选项->Name Resolution,如图2:
    在这里插入图片描述
    图2中红框1部分我在前述已经说明,不在赘述。由于wireshark天然支持GeoIP这种IP数据库文件,只要在红框2的位置添加IP数据库的文件路径即可,其他类型的IP数据库格式并不支持。该种GeoIP数据库文件的官方下载地址,见这里,我在CSDN 也上传了一份较为早期的版本供下载验证,这里。由于早期版本IPV4和IPv6是分开的,因此有6个文件,最新的GeoLite2将两者合并只有三个文件。也通过下载CSV文件直观的查看IP地址和其地理位置信息的映射关系表。除了这三个免费的数据库之外,你会发现 MaxMind 公司网站上还提供了很多的数据库来记录非保留 IP 地址其他方面的信息,包括该 IP 是否是代理,该 IP 是否是匿名 VPN,该 IP 可能对应的域名等等更多方面的信息。但是这些数据库都是收费的,从中可以看出非保留 IP 之所以有这方面的信息是因为非保留 IP 地址通常作为一项服务具有连续性,比如该 IP 地址对应的域名在一两年之内不会发生变化。因此像 MaxMind 就收集了这方面的信息制作成库,同时提供操作的 API。值得注意的是,在数据从 HTTP 逐渐全面过度到 HTTPS 时代,IP 数据库作为分析加密数据一个重要的方面,会显得越来越重要。

    配置完成之后重启一下wireshark就能够解析IP地址的地理位置信息了,整体的配置还是非常的简单。接下来解释一下前面提到的一些基本概念。

    保留 IP 和非保留 IP

    IP 地址用于标示网络中的一台主机,可以分为A、B、C、D、E 这几个类别,区段划分如下:

    • A 类地址:1.0.0.0~126.255.255.255
    • B 类地址:128.0.0.0~191.255.255.255
    • C 类地址:192.0.0.0~223.255.255.255
    • D 类地址:224.0.0.0~224.255.255.255
    • E 类地址:255.0.0.0~255.255.255.255

    A、B、C 三类地址是比较是常见的,D、E 主要用于组播和广播以及研究用途。你会发现 0.0.0.0~0.255.255.255 以及 127.0.0.0~127.255.255.255 这些段的缺失,因为这两段的 IP 有着特殊的用途,均为保留的 IP 段。保留的 IP 段还有很多,像 192.168.1.1 这样的局域网 IP 也属于保留的 IP。因此从这个方面来看 IP 的划分还可以分类两类,即保留的 IP 和非保留的 IP。

    图 3 简单罗列一下IPV4中保留的 IP,摘自维基百科,这里
    enter image description here
    图3
    通过图 3 可以看出保留的 IP 有很多,A、B、C、E 四种类别都有涉及,那么这些 IP 地址在什么情况下使用呢?

    以局域网 为例,选择哪一段保留 IP 地址作为局域网的 ip 地址是跟该局域网内部所容纳设备数量相关的。例如我查看我自己4G手机 上网的 ip 地址就 172.25.81.205,为 B 类 IP 地址,172 这个网段所能容纳的 ip 地址数量为 1048576,手机的 IP 地址是由核心网进行分配的。对于一些小的基站以及核心网设备来说来说百万级别的 IP 应该是完全够用了,如果不够用也可以使用 10 网段的。大公司使用的 ip 地址往往为 10 网段, A 类 IP 地址,例如 10.33.188.106。对于数十万员工级别的公司,各种设备的 IP 很可能超过百万,而 10 网段所能够容纳的 IP 个数在 16777216,这就足够用了。多数学校机房配置的 ip 地址为 192.168.1.115这种形式,192.168 网段能够容纳的 ip 为 655365。而一个学校的机房通常在 10000 以内台,也是够用的。

    以下四点就是我总结的保留 IP 常见的一些作用:

    • 首先全球的 IPV4 地址有限也就 2^32 个,前一段时间IPV4已经正式耗尽。当年为了缓解 IP 地址紧张的问题,相应的解决方法有 IPV6 地址,以及 NAT 转换。但是由于早期 IPV6 并没有普及,主要是老的设备不支持 IPV6 协议栈。因此 NAT 转换是常见的技术手段。NAT 地址转换就是将 192.168.1.115 这样的保留 IP 地址转换为非保留的 IP,192.168.1.115 这样的地址也被称为私网 IP。因此我们看到保留 IP 的第一个作用就是缓解 IP地址资源紧张,不同的局域网可以同时使用同一个保留的 IP。而类似于这样的保留 IP 都是作为客户端的地址。通常来说服务器的 IP都是非保留的 IP,同一时间内,全球唯一的,因为服务器的数量相对于客户端来说还是很少的。当然也是有服务器使用 NAT 等技术的,使用了保留IP。
    • 类似于 255.255.255.255/32 这样的 IP 地址是有着特定的用途的,用于广播。我们知道局域网的广播地址是 MAC 为 ff:ff:ff:ff:ff:ff,在 IP 层的广播地址为 ff.ff.ff.ff。当然 D 类和 E 类的多数 IP地址主要被预留出来。
    • 像 127.0.0.0–127.255.255.255 地址段分配给了本机,通常我们的本地默认回环地址的 IP 就是 127.0.0.1,在本机上测试编写好的网站都是访 http://127.0.0.1:9600/ 这样的地址。通过浏览器访问 http://127.0.0.1:9600/,该流量并不会经过网卡。可以看出操作系统对于 127.0.0.1 这样的 IP数据报文的处理是比较特殊的。
    • 正如前面所提到的 IP 资源有限,同时 IP 地址也是收费的,每年使用者需要向 IP 分配机构缴纳一定的使用费用。因此 IP 数量越少,越节省,这也就是我们 4G 上网 IP 是保留的 IP,家中的宽带也是保留的 IP,学校公司网络多数使用的都是保留IP,只在广域网出口处使用 NAT 将其转换为全局的 IP。

    除了保留 IP,剩下的就是非保留 IP 了。由于保留 IP 同一时间内全球不唯一,因此无法根据保留 IP 定位出其经纬度。而对于非保留 IP 来说,通常也可以被称为公网 IP,由于一段时间内基本不会变化,因此可以统计其经纬度。

    AS Number

    从图 1 中可以看出,该数据库不仅呈现了经纬度,城市等信息,还呈现了 AS Number。AS number 的全称是 Autonomous System (AS) Numbers,也就是自治系统编号。那自治系统又是什么呢?互联网可以认为是由大大小小的自治系统来组成,以中国电信为例,所有的中国电信宽带用户就组成了一个自治系统,当然电信也可能由多个自治系统。同理中国移动和中国联通也有同样的自治系统,全世界的电信运营商,每一家都是一个自治系统。为了管理这些自治系统,需要给每一个自治系统进行统一的编号,那么相应的编号就是 AS number。

    那么由谁来负责这样的编号,世界上由一个组织叫做 IANA,它下面的下属机构几乎管理着互联网相关的一切。这就包括 AS number 的分配,IP 地址的分配等等。在这里可以知道,IANA 将 AS Number 先分配给区域的网络管理机构,由这些机构处理各属辖区的分配和申请工作,例如在这个页面上可以找到著名的电信 AS Number 4134 就是由 APNIC 这样一个亚洲的管理机构进行管理分配的。同时这个页面也给出了 AS Number 的作用,就是用于路由选择协议。

    举个例子来说,很多大型网游都有电信区,联通区域等,通常电信宽带用户会选择电信区,联通宽带用户会选择联通区,这样做的目的是相比交叉选择的情况网速会更快一些。原因在于游戏的电信区是游戏公司部署在电信自治系统的服务器,也就是其 IP 地址是电信的。当电信的宽带用户访问电信区时候,相当于电信这个自治系统内部的通信,而当联通的宽带用户访问电信区游戏服务器的时候,相当于数据在电信这个自治系统和联通这个自治系统之间进行通信。

    网络中通信的基础是 IP 地址,用来表示网络中的唯一一台主机,端口用以表示具体的应用程序。如果通信的层次上升到自治系统之间的话,如上述所描述,自治系统之间通信的基础就是这个 AS Number。当联通的宽带用户访问电信区时候,数据要从联通的自治系统中发出来,首先要找到电信自治系统,关键就是在于联通的边界路由器的路由表中存储了电信的 AS Number,就给数据下一步指明了方向。

    从这里我们可以看出不同自治系统之间需要边界路由器通过 AS Numbe 建立起连接,而自治系统内部通常不需要,所以速度上会有一定的差别。另外像三大运营商之间是竞争关系,用户的体验在于网速、时延,那么中国电信在转发数据报文的时候,肯定是优先电信自己内部的报文,对于联通的报文优先级肯定要靠后的。从这个角度来说,就不难明白为什么游戏要分区了。当然游戏的这个例子是用户主动区选择电信,联通或者移动。再举一个例子说明用户是如何被动选择的。

    对于百度这样的搜索引擎服务上,服务器都是几十万甚至上百万数量级的。为了让用户在速度上有更好的体验,肯定也是希望电信宽带用户访问百度部署在电信自治系统的服务器 IP 的,这个时候就需要 DNS 解析服务器判断请求的 IP 的 AS number,来决定 DNS 应该返回哪一个自治系统的 IP 了。因此可以看出百度在三大运营商的自治系统内都有服务器的部署。

    以上就是对于wireshark如何配置解析IP地址以及 IP 相关概念的一些概述,主要是讲述了保留 IP 和非保留 IP 概念,AS number 的概念,希望通过本文,对你有所启发。

    本文为CSDN村中少年原创文章,未经允许不得转载,博主链接这里。

    展开全文
  • 地理位置是定位用户的重要关键词之一,广告平台Moasis把目标用户按地理位置区域分成小块,方便广告主精确投放广告。 Moasis今天发布了“Geo-Grid(地理位置方格)展示平台”。用户市场基于地理位置被切分成小方格,...

    地理位置是定位用户的重要关键词之一,广告平台Moasis把目标用户按地理位置区域分成小块,方便广告主精确投放广告。

    Moasis今天发布了“Geo-Grid(地理位置方格)展示平台”。用户市场基于地理位置被切分成小方格,广告主可以选择他们希望投放广告的区域。Golden认为这将让广告主们更精确的控制他们的选择,比如他们可以选择几块小区域,几个相邻区域,一个城市等等。由下图我们看出,Geo-Grid将纽约切成了很多小方块。

    Moasis的使用非常简单,首先创建一个“localizement”,选择想要投放广告的区域,添加一些规则比如展示时间等,再输入价格就完成了整个过程。这个平台还允许广告主实时更改他们的价格和合作伙伴。作为对比,Google Adwords的地理位置广告是让客户在地图上画自定义的圆,这在操作和实时交易上存在一定难度,这也是Geo-Grid的竞争优势吧。

    联合创始人兼CEO Ryan Golden表示,大多数的广告公司都是从工程师的角度去看问题的,但Moasis是从市场营销人员的角度来看待这一问题,从而能够更好的把握客户需求(Golden已经创建过好几家营销公司了,他还在数字传媒公司Tribal DDB工作过。)

    值得一提的是,这家公司目前没有引入任何外部投资,所需资金来自自身盈利。



    展开全文
  • 根据经纬度获取地理位置

    热门讨论 2013-03-07 17:09:38
    java 根据经纬度获取地理位置
  • 如何获取用户的地理位置-浏览器地理位置(Geolocation)API 简介 一、总结 一句话总结:Geolocation API(地理位置应用程序接口)提供了一个可以准确知道浏览器用户当前位置的方法。且目前看来浏览器的支持情况还算...
  • elasticsearch 深入 —— 地理位置

    千次阅读 2018-09-13 15:39:59
    地理位置 我们拿着纸质地图漫步城市的日子一去不返了。得益于智能手机,我们现在总是可以知道 自己所处的准确位置,也预料到网站会使用这些信息。我想知道从当前位置步行 5 分钟内可到的那些餐馆,对伦敦更大范围...
  • 基于地理位置的数据挖掘

    千次阅读 2016-12-23 16:46:51
    一般我们在做数据挖掘过程中地理位置算是一个特别重要的特征,广泛应用于O2O的很多场景。但做的事情都相对来说比较...原来我们基于地理位置拿了不少数据,也做了一些模型,主要是一些医院位置、商场位置、公交地
  • Redis地理位置系列GEO

    万次阅读 2019-06-06 20:31:31
    GEO功能在Redis3.2版本提供,支持存储地理位置信息用来实现诸如附近位置、摇一摇这类依赖于地理位置信息的功能.geo的数据类型为zset. 目录 geoadd geopos geodist georadius georadiusbymember geohash zrem...
  • ElasticSearch之基于地理位置的搜索

    千次阅读 2019-08-15 22:32:11
    我们希望搜索到某个区域内的特定目标建筑物,或者说要查询某个城市某个区内的楼盘等,诸如此类的需求,还有我们看到的在百度地图或者高德地图上,在某个区域内显示出我们关心的数据,都可以算是一种基于地理位置的...
  • 我的stackoverflow前言:地理位置编程是iOS开发中常用的技术。常用的就是定位获取当前的位置,部分App需要动态监听地理位置变化以及导航。本文以获取当前的地理位置为例,进而详细讲解位置编程相关的类。注意:只有...
  • java根据ip地址获取用户地理位置

    万次阅读 2019-04-25 17:00:07
    工作项目需要,根据用户向服务器请求的ip地址获取用户所在的地理位置。 具体代码      话不多说,直接上代码(作为一个负责任的程序员,我把import内容都贴贴出来了): /** * FileName: ...
  • 目前在做公司的一个网站,有个需求是:当别人进入网站时自动定位他的地理位置,包括市区,方便给他推荐当前城市的特色信息。 其实,这也是一个非常实用的功能,在网上搜到很多,有的不能用,现将我整理的两个能用的...
  • 将ip转换为地理位置存入elasticsearch

    千次阅读 2019-11-07 18:25:49
    有些需要将一些数据基于地址位置进行分析,比如哪些区域比较活跃,在什么时间范围内活跃,但是后端仅能获取ip地址,因此需要将ip地址转换为地理位置,幸运的是我们有开源的工具可以使用,maxmind/GeoIP2-java使用...
  • iOS中的地理位置的获取及plist设置

    千次阅读 2017-02-28 10:32:23
    1.在前台的时候获取地理位置信息 ios 8/9 在info.plist中配置NSLocationWhenInUseUsageDescription的值,否则上面的方法无效 调用.requestWhenInUseAuthorization()获取前台获取地理位置权限 调用...
  • Python根据IP查找所在地理位置与运营商 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 ...
  • Elasticsearch 地理位置范围查询

    千次阅读 2017-01-18 16:31:36
    elasticsearch地理位置范围查询 Geo Distance Range Query
  • PC端google chrome真正实现地理位置模拟,HTML5 - 使用地理定位 的正确实现方法
  • 逆地理编码——获取地理位置

    千次阅读 2014-11-26 15:48:55
    具体需求:根据地理坐标:39.831782,116.347120,向用户展示地理位置:丰台区 我们可以参考百度,阿里等的web服务api进行逆地理编码。 阿里:http://gc.ditu.aliyun.com/jsdoc/geocode_api.html#a1_5 百度:...
  • Vue 获取当前地理位置信息

    千次阅读 2020-05-11 11:35:43
    两个参考: https://blog.csdn.net/YY110621/article/details/87921605 ... ... 也直接放代码,虽然是转载. ...-- 获取地理位置 这个key是申请的 感谢--> <script type="text/javascript" src="https://webapi..
  • chrome浏览器配置,地理位置模拟

    千次阅读 2018-11-13 17:38:52
    chorme浏览器版本: 70.0.3538.77     注意事项 页面地址如: http://localhost:63300/app-h5/pages/map/fault.html ...才能获取到地理位置 ...用内网IP,是获取不到地理位置的 http://192.1...
  • Redis GEO地理位置

    万次阅读 2016-07-09 17:18:51
    但是大多数时候,只是想获取某个地理位置附近的其他地理位置,使用GEORADIUSBYMEMBER则更为方便 127.0.0.1:6386> georadiusbymember user xiaoming 1500 km WITHDIST 1) 1) “xiaohong” 2) “1070.4292” ...
  • mysql 5.7.28 空间地理位置计算

    千次阅读 2020-01-07 14:22:49
    mysql 5.7.28 空间地理位置计算1. 创建测试表2. 插入数据3. 计算两个坐标点之间的距离4. 计算指定的坐标点是否位于多边形(面)中5. 计算两个多边形(面)是否相交 (st_intersects )6. 计算两个多边形(面)是否...
  • 最近需要对GPS定位信息进行地理位置解析,看到一些博客文章里面建议使用百度地图API来做,不过考虑到百度地图在国外的使用体验,我还是想试试通过Google地图来进行地理位置获取,闲话不多说,上代码。 首先当然需要...
  • mysql 5.7.28 地理位置计算详解

    千次阅读 2020-02-27 17:51:16
    mysql 5.7.28 空间地理位置计算1. 创建测试表2. 插入数据3. 计算两个坐标点之间的距离4. 计算指定的坐标点是否位于多边形(面)中4.1 第一种方式4.2 第二种方式5. 计算两个多边形(面)是否相交 (st_intersects )6...
  • Redis教程(八) GEO地理位置

    千次阅读 2017-04-27 14:12:40
    Redis教程(八) GEO地理位置 1 GEO地理位置 Redis的键值可以支持数据类型:字符串,列表,散表,集合,有序集合、HyperLogLog,通过选用不同的数据结构,用户可以使用Redis解决各式各样的问题。 1.1...
  • 最近想做一个简单的地理位置分析,比如获取一些城市公交站点对应的geohash,geohash其实是将平时常见的经纬度进行了降维,这样可以进行类似附近的餐馆等内容的分析。 1. 正逆地理编码 ...正/逆地理编码服务(又名...
  • 用户地理位置的聚类算法实现—基于DBSCAN和Kmeans的混合算法用户地理位置的聚类算法实现基于DBSCAN和Kmeans的混合算法 聚类算法简介 1 基于划分的Kmeans算法 2 基于密度的DBSCAN算法 用户地理位置信息的的聚类实现 1...
  • 阿里云 数加平台, Quick BI 做报表 仪盘表 多表联动 地理位置 地理信息 没有数据 数据源 maxCompute
  • 前端使用js根据ip地址获取城市地理位置   一、使用js根据ip获取地址位置 1、在html页面,加入如下代码: &lt;script src="http://pv.sohu.com/cityjson?ie=utf-8"&gt;&lt;/script&...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 36,638
精华内容 14,655
关键字:

区域地理位置