近期作为突击队员,与同事一起突击构建了一个简单的lbs系统。当前比较主流的做法是使用mongodb,因为其已经封装了常用的lbs基本操作(如查找附近的人),功能非常强大,对于开发周期只有一周的项目,mongodb真可谓是救世主,把最重要的需求给完成了,谢天谢地!

mongodb是比较著名的nosql db,想了解的同学不妨问问谷歌或度娘,对于专业问题本人倾向于问谷歌。本文还参考了这篇文章。我们使用的是目前最新版本的mongodb-2.4.9。

首先从mongodb提供的lbs功能讲起:mongodb支持以下几种查询:

1.区域内搜索:所谓区域内搜索,即列出附近一定范围内的所有记录,如baidu地图的“附近”。mongodb使用$geoWithin命令即可实现此类查询,其强大之处在于支持矩形区域($box)、圆形区域( $center)和多边形区域( $polygon)查询!以圆形区域查询为例,只需要给出圆心的经纬度和查询半径,就可以取到在该区域内的所有记录,不过返回结果是无序的。

2.查找附近:查找附近即将某一个位置附近的记录按照由近到远的顺序返回,如很多社交app的查找附近的人。mongodb使用$near命令,输入中心点的坐标即可返回结果,结果是按照距离由小到大排序好的。$near接口比$geoWithin多了一步排序,但对2维坐标建索引的话,二者的查询效率基本相同。

另外还有一个命令是$geoNear,可以认为是$near的升级版,除了返回记录之外还会返回距离及其他诊断信息。我们的应用需要计算距离,一开始就想使用这个命令,但是其使用很不方便。很奇怪的,该命令不能像$near和$geoWithin般可以和find命令集成,使用过程中很不灵活,无法完全满足我们的应用需求。

其次说说距离计算

MongoDB地理位置索引常用的有两种:1)2d 平面坐标索引,适用于基于平面的距离计算。2)2dsphere 几何球体索引,适用于球面几何距离运算。追求百分之百的精确,应选择2dsphere。不过,在坐标跨度不太大(如两千公里以内),这两个索引计算出的距离相差几乎可以忽略不计。关于mongodb实现的2维地理位置索引,可以参考这篇文章,写的简单易懂。

接下来说说实践中碰到的复合索引的使用。因为mongodb是个开源项目,总会有些不完善的地方,而这些问题也只有使用的时候才会碰到。

复合索引即对多个字段联合建立索引,假设在一个mongo集合(collection)的记录含有A和B两个字段,我们要查询A大于0且B大于100的记录,显然A、B的复合索引{“A”:1,”B”:1}可以有效提高这类查询的效率,mongodb也做到了。该查询用mongo的语言描述为:db.posts.find({ “A”:{$gt:0}, “B”:{$gt:100} } )。但如果我们要得到A大于0且按照B升序排序的记录,刚才建立的联合索引就不起作用了。这个查询用mongo的语言描述为:db.posts.find({ “A”:{$gt:0}} ).sort({“B”:1})。

而且即使对所取记录总数做限制也无法提高查询效率。例如我假设复合条件的记录共有2000条,我只取100条,即db.posts.find({ “A”:{$gt:0}} ).sort({“B”:1}).limit(100)。按我的理解,如果复合索引起作用,不管limit与否都应该很快。但测试下来发现,查询的时间跟符合条件的记录总数成正比,即2000条取100条要50ms,而1000条取100条就只要30ms,似乎是不管limit多少,mongo会把所有满足find条件的记录全部读到内存,再根据sort的条件进行排序。这排序恰恰是性能的瓶颈所在,如果去除排序,2000条取100条也只要10ms左右,查询A大于0且B大于100的记录也是只要100ms。

老外的分析,这个是mogodb目前的bug,应该会在2.6版本fix掉,希望如此吧。目前也没有什么办法可以优化这个问题,只能在find的时候通过更多的限制条件,减少被排序的记录数目,但在面对实际需求时往往不能这么做。

所以,此次项目学到的经验是,开源项目的确有非常强大的功能,帮我们解决了大部分基础问题,也常常给我们很多惊喜(如mongo对地理信息查询的强大而全面的支持)。不过,所谓“天下没有免费的午餐”,使用开源项目不仅需要学习怎么用,使用过程中也会遇到一些坑,需要交点学费,所以,要时刻保持谨慎和批判的态度。

利用mongodb开发lbs应用实践【转】的更多相关文章

  1. 结合MongoDB开发LBS应用(转)

    原文链接:结合MongoDB开发LBS应用 简介 随着近几年各类移动终端的迅速普及,基于地理位置的服务(LBS)和相关应用也越来越多,而支撑这些应用的最基础技术之一,就是基于地理位置信息的处理.我所在 ...

  2. 深入浅出Symfony2 - 结合MongoDB开发LBS应用

    简介 随着近几年各类移动终端的迅速普及,基于地理位置的服务(LBS)和相关应用也越来越多,而支撑这些应用的最基础技术之一,就是基于地理位置信息的处理.我所在的项目也正从事相关系统的开发,我们使用的是S ...

  3. 结合MongoDB开发LBS应用

    然后列举一下需求:1.实时性要高,有频繁的更新和读取2.可按距离排序支持分页3.支持多条件筛选(一个经纬度数据还包含其他属性,比如社交系统的性别.年龄) 方案简单介绍:1.sphinx geo索引支持 ...

  4. MongoDB开发最佳实践

    MongoDB开发最佳实践 连接到MongoDB · 关于驱动程序:总是选择与所用之MongoDB相兼容的驱动程序.这可以很容易地从驱动兼容对照表中查到: · 如果使用第三方框架(如Spring Da ...

  5. 利用Sails.js+MongoDB开发博客系统

    http://yoyoyohamapi.me/categories/利用Sails-js-MongoDB开发博客系统/ 利用Sails.js+MongoDB开发博客系统 Apr 14, 2016 利用 ...

  6. 如何利用MongoDB实现高性能,高可用的双活应用架构?

    投资界有一句至理名言——“不要把鸡蛋放在同一个篮子里”.说的是投资需要分解风险,以免孤注一掷失败之后造成巨大的损失. 转发来自 如何利用MongoDB实现高性能,高可用的双活应用架构?http://d ...

  7. 20145308刘昊阳 《Java程序设计》实验三 敏捷开发与XP实践 实验报告

    20145308刘昊阳 <Java程序设计>实验三 敏捷开发与XP实践 实验报告 实验名称 敏捷开发与XP实践 实验内容 XP基础 XP核心实践 相关工具 统计的PSP(Personal ...

  8. 20145215实验三 敏捷开发与XP实践

    20145215实验三 敏捷开发与XP实践 实验内容 XP基础 XP核心实践 相关工具 实验步骤 (一)敏捷开发与XP 软件工程是把系统的.有序的.可量化的方法应用到软件的开发.运营和维护上的过程.软 ...

  9. 利用WinDriver开发PCI设备驱动程序

    摘要 WinDriver是Jungo公司出版的一个设备驱动程序开发组件,它可以大大加速PCI设备驱动程序的开发.作者在实际的项目中采用了WinDriver来开发设备驱动程序,取得了相当好的运行效果.从 ...

随机推荐

  1. 如何让Activiti-Explorer使用sql server数据库

    从官网下载的Activiti-explorer的war文件内部默认是使用h2内存数据库的,如果想改用其他的数据库来做持久化,比如sql server,需要做如下配置. 1)修改db.propertie ...

  2. 轻松使用Nginx搭建web服务器

    如果读者以前做过web开发的话,就应该知道如何去搭建一个web服务器来跑你的web站点,在windows下你可能会选择去用IIS,十分的快捷,在linux下,你可能首先会想到apache,“一哥”( ...

  3. QT使用UAC(经过验证)

    网上有很多manifest的版本,mingw与vs系列也有不同的解决方案,不管那么多,我是使用这篇文章解决这个问题的: So it turns out that I had another bug t ...

  4. 《ArcGIS Engine+C#实例开发教程》第七讲 图层符号选择器的实现2

    原文:<ArcGIS Engine+C#实例开发教程>第七讲 图层符号选择器的实现2 摘要:在第七讲 图层符号选择器的实现的第一阶段中,我们完成了符号选择器窗体的创建与调用.在第二阶段中, ...

  5. linux下查看防火墙当前状态,开启关闭等

    从配置菜单关闭防火墙是不起作用的,索性在安装的时候就不要装防火墙 查看防火墙状态: /etc/init.d/iptables status 暂时关闭防火墙: /etc/init.d/iptables  ...

  6. BZOJ1324: Exca王者之剑

    1324: Exca王者之剑 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 256  Solved: 131[Submit][Status] Desc ...

  7. [Bhatia.Matrix Analysis.Solutions to Exercises and Problems]ExI.2.3

    (1). Let $\sed{A_\al}$ be a family of mutually commuting operators. Then, there exists a common Schu ...

  8. 【原】Spark中Client源码分析(一)

    在Spark Standalone中我们所谓的Client,它的任务其实是由AppClient和DriverClient共同完成的.AppClient是一个允许app(Client)和Spark集群通 ...

  9. bat 批处理 字符串 截取

    由于项目中配置项太多,经常有同事在配置xml的时候,讲 配置的路径搞错,先需要搞一个脚本,可以自动将路径截取出来, 晚上收集了点资料,暂时先上几个 bat 后面留着 ,具体实现. @echo off ...

  10. Git 钩子

    1. 概念概述 1.1. 安装钩子 1.2. 脚本语言 1.3. 钩子的作用域 2. 本地钩子 2.1. 预提交钩子 Pre-Commit 2.2. 准备提交信息钩子 Prepare Commit M ...