做LBS应用有多种方案,这里介绍一下在Laravel5中使用Mongodb来实现,文章参考了:
深入浅出Symfony2 - 结合MongoDB开发LBS应用
环境说明:
首先下载最新的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
首先到官网下载对应的版本:
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()
(未完待续,今天有事,写不完了,改日再来!)
========2015-11-28=============
今天继续,把laravel实现这一部分写完。
在进行相关的代码操作前,需要完成laravel相关的环境设置:
database.php
内容如下:'connections' => [
....
'mongodb' => [
'driver' => 'mongodb',
'host' => 'localhost',
'port' => '27017',
'database' => 'test',
'username' => '',
'password' => '',
],
]
$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中后,需要对数据建立地理位置索引,它的索引方式有两种:
既然官方已经推荐使用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专题目录