12.Laravel5学习笔记:使用mongodb开发LBS应用

做LBS应用有多种方案,这里介绍一下在Laravel5中使用Mongodb来实现,文章参考了:
深入浅出Symfony2 - 结合MongoDB开发LBS应用

环境说明:

  • php集成环境:xampp
  • centos7

一、安装php的mongodb扩展

首先下载最新的php mongodb扩展源码,源码可以在http://pecl.php.net/package/mongo下载到

# wget http://pecl.php.net/get/mongo-1.6.12.tgz
# tar -zxvf mongo-1.6.12.tgz
# cd mongo-1.6.12

进入文件夹后,首先运行phpize来准备编译扩展的环境

# phpize

环境准备完后,执行以下命令进行安装

# ./configure --with-php-config=/opt/lampp/bin/php-config
# make && make install

然后有时候常常会报以下错误:

这是由于openssl没有安装,使用以下方式安装一下:

# yum install openssl openssl-devel

然后再执行 make && make install
执行后,可以看到:

这时,表示执行成功了。
此时,还需要修改php.ini文件,这个已经说过很多次。操作如下:
打开文件,在末尾添加如下内容:

[Mongodb]
extension=mongo.so

二、安装mongodb

首先到官网下载对应的版本:
https://www.mongodb.org/downloads#production
这里需要注意选择自己对应的linux版本。

# wget http://fastdl.mongodb.org/linux/mongodb-linux-x86_64-3.0.7.tgz
// 注意,这里官网上是https协议,但是下载会遇到问题,请改为http协议
# tar -zxvf mongodb-linux-x86_64-3.0.7.tgz
# mv mongodb-linux-x86_64-3.0.7 /usr/local/mongoDB
# export PATH=/usr/lcoal/mongoDB/bin:$PATH
# mkdir -p /data/db

该安装非常的简单,现在运行一下,进行测试 mongod ,然后使用mongo 链接一下,如果能够成功,则正确。

这里在额外讲一下,默认情况下,直接使用 mongod启动的服务,当关闭shell时,服务也就自动关闭了。因此常常需要将服务以守护进程的方式进行启动,方式如下:

# mongod --fork --logpath /var/log/mongodb.log

启动后,关闭shell后,然后可以访问mongodb服务。
这里在备注一下,mongodb的服务停止方式,进入到客户端,执行以下操作:

use admin
db.shutdownServer()

三、Laravel实现

(未完待续,今天有事,写不完了,改日再来!)

========2015-11-28=============
今天继续,把laravel实现这一部分写完。
在进行相关的代码操作前,需要完成laravel相关的环境设置:

  • 首先,确保前面两步已经操作完成。
  • 修改config文件夹中的,database.php 内容如下:
'connections' => [
    ....
    'mongodb' => [
        'driver'   => 'mongodb',
        'host'     => 'localhost',
        'port'     => '27017',
        'database' => 'test',
        'username' => '',
        'password' => '',
    ],
]
  • 接下来把数据库中多条记录读出来,并插入到mongodb中即可。代码简介如下:
$mongodb = DB::connection('mongodb');
$db = $mongodb->collection('user');

$addrs = Address::get();
foreach ($addrs as $key => $addr) {
    $values = [
        '_id' => $addr->id,
        'loc' => [
            'longitude' => (float)$addr->longitude,
            'latitude' => (float)$addr->latitude,
        ],
    ];

    $db->insert($values);
}

当然,在这里,你可以将你想要加入的数据,全部放入到mongodb中去,我这里为了做演示,就只放入需要的经纬度即可,有个小点需要提醒注意:经纬度需要使用浮点型进行保存,请不要存为字符串了。

当所有数据插入到mongodb中后,需要对数据建立地理位置索引,它的索引方式有两种:

  • 2d 平面坐标索引,适用于基于平面的坐标计算。也支持球面距离计算,不过官方推荐使用2dsphere索引。
  • 2dsphere 几何球体索引,适用于球面几何运算

既然官方已经推荐使用2dsphere,我肯定会用它的,实际上我在自己本地测试时,也使用了2d索引方式,但是还是会出现一些问题,不信你可以自己玩玩。
使用mongo shell链接上mongodb服务,建立索引:

db.places.ensureIndex({‘loc’:’2dsphere’})
我这里主要实现了以下两种查询方式:

  • 因为有获取附近的XXX,索引需要根据定位的经纬度,获取多少范围(km)的XXX,并且有序返回;

  • 还因为有地图模式,不需要排序,只需要获取范围内的信息。

实现这两种的条件非常简单,代码如下:

/** * * * @desc 根据mongodb获取附近的门店信息 * mongodb的索引需要支持2dsphere * @author dayu <[email protected]> * @date 2015年11月28日 */
class NearbySeller {
    private $longitude;#经度
    private $latitude;#纬度
    private $mongodb;

    /** * 初始化 * * @param string $collection 需要操作的集合 * @param float $longitude 经度 * @param float $latitude 纬度 */
    public function __construct($collection, $longitude, $latitude) {
        $this->longitude = (float)$longitude;
        $this->latitude = (float)$latitude;

        $this->mongodb = MongoClient::getInstance()->collection($collection);
    }

    /** * 搜索多少km内的信息,由近到远的顺序返回 * @param integer $kilometer 获取多少km内的信息 * @param integer $perPage 获取多少数据,每页 * @param integer $page 获取的第几页, * * @return 返回获取到的地址距离 */
    public function getRangeBySort($kilometer, $perPage, $page) {
        $where = [
                'loc' => [
                        '$nearSphere' => [
                                '$geometry' => [
                                        'type' => 'Point',
                                        'coordinates' => [$this->longitude, $this->latitude]
                                ],
                                '$maxDistance' => $kilometer*1000
                        ]
                ],
        ];

        $list = $this->mongodb->whereRaw($where)->skip(($page-1) * $perPage)->take($perPage)->get();

        return $list;
    }

    /** * 搜索多少km内的信息,由近到远的顺序返回 * @param integer $kilometer 获取多少km内的信息 * * @return 返回获取到的地址距离 */
    public function getRadiusBydisorder($kilometer) {
        $where = [
                'loc' => [
                        '$geoWithin' => [
                                '$centerSphere' => [
                                        [
                                                $this->longitude,
                                                $this->latitude
                                        ],
                                        $kilometer/6371
                                ]
                        ]
                ],
        ];

        $list = $this->mongodb->whereRaw($where)->get();

        return $list;
    }

测试使用:

$near = new NearbySeller('supplier', 104.07172, 30.574907);
$page = $request->input('page', 1);
$perPage = 3;

// 测试获取多少km以内的门店信息,列表模式
$list = $near->getRangeBySort(4, $perPage, $page);

// 测试多少km半径内的门店信息,地图模式
$list = $near->getRadiusBydisorder(4, $perPage, $page);

通过上面返回的数据,你会看到,第一个方法返回的数据距离是有序的,第二个方法返回的距离时无序的(因为是地图模式,只获取范围内所有信息即可)

基本操作就完了,其实这里还涉及到很多mongodb方面的查询只是,已经mongodb的一些查询命令,精力因素,就不便于全部写出了,而且在文章开头的部分,我分享的哪篇文章也说的很多,只是由于版本,可能与最新版稍微有些不一致。
好了这篇文章就写到这里吧。

Laravel5专题目录

你可能感兴趣的:(mongodb,LBS,laravellbs,php+lbs)