• Mysql or Mongodb LBS快速实现方案


    http://www.wubiao.info/470

    前两篇文章:

    查找附近的xxx 球面距离以及Geohash方案探讨 (http://www.wubiao.info/372

    微信、陌陌 架构方案分析 (http://www.wubiao.info/401

    探讨了,LBS查找附近的XXX;其中包括了,Mysql自定义存储函数方案,以及通过GeoHash、redis自建索引方案。

    ===============================================================

    今天分享两种,利用GeoHash封装成内置数据库函数的简易方案;

    A:Mysql 内置函数方案,适合于已有业务,新增加LBS功能,增加经纬度字段方可,避免数据迁移

    B:Mongodb 内置函数方案,适合中小型应用,快速实现LBS功能,性能优于A(推荐)

    ===============================================================

    方案A: (MySQL Spatial)

    1、先简历一张表:(MySQL 5.0 以上 仅支持 MyISAM 引擎)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    CREATE TABLE address (
     
        address CHAR(80) NOT NULL,
     
        address_loc POINT NOT NULL,
     
        PRIMARY KEY(address)
     
    );

    空间索引:

    1
    ALTER TABLE address ADD SPATIAL INDEX(address_loc);

    插入数据:(注:此处Point(纬度,经度) 标准写法)

    1
    2
    3
    INSERT INTO address VALUES('Foobar street 12', GeomFromText('POINT(30.620076 104.067221)'));
     
    INSERT INTO address VALUES('Foobar street 13', GeomFromText('POINT(31.720076 105.167221)'));

    查询: 查找(30.620076,104.067221)附近 10 公里

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    SELECT  *
        FROM    address
        WHERE   MBRContains
                        (
                        LineString
                                (
                                Point
                                        (
                                        30.620076 + 10 / ( 111.1 / COS(RADIANS(104.067221))),
                                        104.067221 + 10 / 111.1
                                        ),
                                Point
                                        (
                                        30.620076 - 10 / ( 111.1 / COS(RADIANS(104.067221))),
                                        104.067221 - 10 / 111.1
                                        )
                                ),
                        address_loc
                        )

    方案B:

    1、先建立一张简单的表user,两条数据如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    {
      "_id": ObjectId("518b1f1a83ba88ca60000001"),
      "account": "simplephp1@163.com",
      "gps": [
        104.067221,
        30.620076
      ]
    }
     
    {
      "_id": ObjectId("518b1dae83ba88d660000000"),
      "account": "simplephp6@163.com",
      "gps": [
        104.07958,
        30.653936
      ]
    }

    其中,gps为二维数组,分别为经度,纬度

    (注:此处必须按照(经度,纬度)顺序存储。我们平时表示经纬度,都是(纬度,精度),此处这种方式有木有很亲民)

    2、使用之前,先建立二维索引

    //建立索引 最大范围在经度-180~180

    1
    db.user.ensureIndex({"gps":"2d"},{"min":-180,"max":180})

    //删除索引

    1
    db.user.dropIndex({"gps":"2d"})

    3、Mongodb有两中方式可以查找附近的XXX;其中方案2)会返回距离(推荐)

    1)标准查询,为地球经纬度查询内置;参数一为查询条件利用$near查找附近,参数二$maxDistance为经纬弧度(1° latitude = 111.12 kilometers)即 1/111.12,表示查找附近一公里。

    1
    db.user.find({ gps :{ $near : [104.065847, 30.657554] , $maxDistance : 1/111.12} })

    2)执行命名方式,模拟成一个圆球;参数一指定geoNear方式和表名;参数二坐标,参数三是否为球形,参数四弧度(弧度=弧长/半径 一千米的弧度1000/6378000),参数五指定球形半径(地球半径)

    1
    db.runCommand({geoNear:'user', near:[104.065847, 30.657554], spherical:true, maxDistance:1000/6378000, distanceMultiplier:6378000});

    本条目发布于2013年05月28日。属于DB架构算法分类,被贴了  标签。

  • 相关阅读:
    [MySQL] InnoDB三大特性之 插入缓冲
    字节对齐《c和指针》笔记包含位域结构体的内存对齐(32bit,GCC)
    反编译想到的代码安全问题
    剪切\编辑歌曲软件
    照片行【生活随笔】井冈山之行
    埃里克食品浅谈垃圾食品
    C++ 堆排序实现
    SQLite数据库
    全光网络的前世今生
    hdu1201(从出生长18岁经过多少天)
  • 原文地址:https://www.cnblogs.com/kenshinobiy/p/4311428.html
Copyright © 2020-2023  润新知