首页 程序笔记 c#使用MongoDB开发LBS应用

c#使用MongoDB开发LBS应用

MongoDB下载地址

http://www.mongodb.org/downloads

.NET驱动

https://github.com/mongodb/mongo-csharp-driver

MongoDB常用命令:

成功启动MongoDB后,再打开一个命令行窗口输入mongo,就可以进行数据库的一些操作。

输入help可以看到基本操作命令:

show dbs:显示数据库列表 

show collections:显示当前数据库中的集合(类似关系数据库中的表) 

show users:显示用户

use <db name>:切换当前数据库,这和MS-SQL里面的意思一样 

db.help():显示数据库操作命令,里面有很多的命令 

db.foo.help():显示集合操作命令,同样有很多的命令,foo指的是当前数据库下,一个叫foo的集合,并非真正意义上的命令 

db.foo.find():对于当前数据库中的foo集合进行数据查找(由于没有条件,会列出所有数据) 

db.foo.find( { a : 1 } ):对于当前数据库中的foo集合进行查找,条件是数据中有一个属性叫a,且a的值为1

理位置索引:

MongoDB地理位置索引常用的有两种。

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

2dsphere 几何球体索引,适用于球面几何运算。

关于两个坐标之间的距离,官方推荐2dsphere:

MongoDB supports rudimentary spherical queries on flat 2d indexes for legacy reasons. In general, spherical calculations should use a 2dsphere index, as described in 2dsphere Indexes.

不过,只要坐标跨度不太大(比如几百几千公里),这两个索引计算出的距离相差几乎可以忽略不计。

建立索引:

> db.places.ensureIndex({'coordinate':'2d'})

> db.places.ensureIndex({'coordinate':'2dsphere'})

查询方式:

查询方式分三种情况:

Inclusion。范围查询,如百度地图“视野内搜索”。

Inetersection。交集查询。不常用。

Proximity。周边查询,如“附近500内的餐厅”。

而查询坐标参数则分两种:

坐标对(经纬度)根据查询命令的不同,$maxDistance距离单位可能是 弧度 和 平面单位(经纬度的“度”):

  db.<collection>.find( { <location field> :

                   { $nearSphere: [ <x> , <y> ] ,

                     $maxDistance: <distance in radians>

                } } )

GeoJson $maxDistance距离单位默认为米:

  db.<collection>.find( { <location field> :

                   { $nearSphere :

                     { $geometry :

                        { type : "Point" ,

                          coordinates : [ <longitude> , <latitude> ] } ,

                       $maxDistance : <distance in meters>

             } } } )

案例A:附近的人

查询当前坐标附近的目标,由近到远排列。

可以通过$near或$nearSphere,这两个方法类似,但默认情况下所用到的索引和距离单位不同。

查询方式:

> db.places.find({'coordinate':{$near: [121.4905, 31.2646]}})

> db.places.find({'coordinate':{$nearSphere: [121.4905, 31.2646]}})

查询结果:

    "_id" : 115, 

    "coordinate" : { 

        "longitude" : 121.4915, 

        "latitude" : 31.25933 

    }, 

    "title" : "仅售148元,市场价298元的星程上服假日酒店全日房一间入住一天,

节假日通用,精致生活,品质享受", 

    "address" : "虹口区天水路90号" 

}

…(100条)

上述查询坐标[121.4905, 31.2646]附近的100个点,从最近到最远排序。

默认返回100条数据,也可以用limit()指定结果数量,如

> db.places.find({'coordinate':{$near: [121.4905, 31.2646]}}).limit(2)

指定最大距离 $maxDistance

> db.places.find({'coordinate':{$near: [121.4905, 31.2646], $maxDistance:2}})

结合Symfony2进行演示:

这里用near,默认以度为单位,公里数除以111(关于该距离单位后文有详细解释)。

/**

 * @Route("/near", name="near")

 * @Template()

 */

public function nearAction(){

    $longitude = (float)$this->getRequest()->get('lon',121.4905);

    $latitude = (float)$this->getRequest()->get('lat',31.2646);

    //2km

    $max = (float)$this->getRequest()->get('max', 2);

    $places = $this->getPlaceRepository()->createQueryBuilder()

        ->field('coordinate')->near($longitude, $latitude)

        ->maxDistance($max/111)

        ->getQuery()->toarray();

    return compact('places','max','longitude','latitude');

}

通过 domain.dev/near 访问,效果如下:

longitude: xxx, latitude: xxx为当前位置,我们在地图上显示了周边100条目标记录

案例B:区域内搜索

MongoDB中的范围搜索(Inclusion)主要用$geoWithin这个命令,它又细分为3种不同类型,如下:

$box 矩形

$center 圆(平面),$centerSphere圆(球面)

$polygon 多边形

$center和$centerSphere在小范围内的应用几乎没差别(除非这个圆半径几百上千公里)。

下面我们介绍一下这三种查询的案例。

矩形区域

这个比较常用,比如百度地图的视野内搜索(矩形)、或搜狗地图的“拉框搜索”

定义一个矩形范围,我们需要指定两个坐标,在MongoDB的查询方式如下:

> db.places.find( 

    { 

        coordinate : { 

            $geoWithin : { 

                $box :[ [ 121.44, 31.25 ] , [ 121.5005, 31.2846 ] ] 

            } 

        } 

    } 

)

查询结果:

    "_id" : 90472, 

    "title" : "【鲁迅公园】仅售99元!酒店门市价288元的上海虹元商务宾馆客房一间入住一天(需持本人有效

身份证件办理登记):大床房/标准房(2选1)!不含早餐!不涉外!2012年9月29日-10月6日

不可使用拉手券!可延迟退房至14:00!", 

    "address" : "上海市虹口区柳营路8号", 

    "coordinate" : { 

        "longitude" : 121.47, 

        "latitude" : 31.27145 

    } 

}

Symfony2演示代码:

指定两个坐标点

/**

 * @Route("/box", name="box")

 * @Template()

 */

public function boxAction(){

    $request = $this->getRequest();

    $longitude = (float)$request->get('lon',121.462035);

    $latitude = (float)$request->get('lat',31.237641);

    $longitude2 = (float)$request->get('lon2',121.522098);

    $latitude2 = (float)$request->get('lat2',31.215284);

    $places = $this->getPlaceRepository()->createQueryBuilder()

        ->field('coordinate')->withinBox($longitude, $latitude, 

$longitude2, $latitude2)

        ->getQuery()->toarray();

    return compact('places','longitude','latitude', 'longitude2', 'latitude2');

}

圆形区域

应用场景有:地图搜索租房信息

查询以某坐标为圆心,指定半径的圆内的数据。

前面已提到,圆形区域搜索分为$center和$centerSphere这两种类型,它们的区别主要在于支持的索引和默认距离单位不同。

2d索引能同时支持$center和$centerSphere,2dsphere索引支持$centerSphere。关于距离单位,$center默认是度,$centerSphere默认距离是弧度。

查询方式如下:

> db.places.find({'coordinate':{$geoWithin:{$centerSphere:[ [121.4905, 31.2646] ,

0.6/111] }}})

> db.places.find({'coordinate':{$geoWithin:{$centerSphere:[ [121.4905, 31.2646] ,

0.6/6371] }}})

查询结果

    "_id" : 115, 

    "coordinate" : { 

        "longitude" : 121.4915, 

        "latitude" : 31.25933 

    }, 

    "title" : "仅售148元,市场价298元的星程上服假日酒店全日房一间入住一天,节假日通用,

精致生活,品质享受", 

    "address" : "虹口区天水路90号" 

}

Symfony2演示代码:

指定圆心坐标和半径

/**

 * @Route("/center", name="center")

 * @Template()

 */

public function centerAction(){

    $request = $this->getRequest();

    $longitude = (float)$request->get('lon',121.4905);

    $latitude = (float)$request->get('lat',31.2646);

    //10km

    $max = (float)$request->get('max', 10);

    $places = $this->getPlaceRepository()->createQueryBuilder()

        ->field('coordinate')->withinCenter($longitude, $latitude, $max/111)

        ->getQuery()->toarray();

    return compact('places','max','longitude','latitude');

}

以longitude: xxx,latitude: xxx为中心点,半径10km的圆内

多边形

复杂区域内的查询,这个应用场景比较少见。指定至少3个坐标点,查询方式如下(五边形):

> db.places.find( { coordinate : { $geoWithin : { $polygon : [ 

    [121.45183 , 31.243816] ,

    [121.533181, 31.24344] ,

    [121.535049, 31.208983] ,

    [121.448955, 31.214913] ,

    [121.440619, 31.228748]

] } } } )

查询结果

    "_id" : 90078, 

    "title" : "仅售9.9元,市场价38元的燕太太燕窝单人甜品餐,用耐心守候一盅炖品,用爱滋补一生情谊", 

    "address" : "河南南路489号香港名都购物广场1F125燕太太燕窝", 

    "coordinate" : { 

        "longitude" : 121.48912, 

        "latitude" : 31.22355 

    } 

}

Symfony2演示代码(这里为方便,直接写死了5个坐标点):

/**

 * @Route("/polygon", name="polygon")

 * @Template()

 */

public function polygonAction(){

    $points = [];

    $points[] = [121.45183,31.243816];

    $points[] = [121.533181,31.24344];

    $points[] = [121.535049,31.208983];

    $points[] = [121.448955,31.214913];

    $points[] = [121.440619,31.228748];

    $sumlon = $sumlat = 0;

    foreach($points as $p){

        $sumlon += $p[0];

        $sumlat += $p[1];

    }

    $center = [$sumlon/count($points), $sumlat/count($points)];

    $places = $this->getPlaceRepository()->createQueryBuilder()

        ->field('coordinate')->withinPolygon($points[0], $points[1], $points[2], 

$points[3], $points[4])

        ->getQuery()->toarray();

    return compact('places','points', 'center');

}

案例C:附近的餐厅

我们假设需要以当前坐标为原点,查询附近指定范围内的餐厅,并直接显示距离。

这个需求用前面提到的$near是可以实现的,但是距离需要二次计算。这里我们用$geoNear这个命令查询。

$geoNear与$near功能类似,但提供更多功能和返回更多信息,官方文档是这么解释的:

The geoNear command provides an alternative to the $near operator. In addition to the functionality of $near, geoNear returns additional diagnostic information.

查询方式如下(关于下面的示例用到了distanceMultipler函数,后文会详细解释):

> db.runCommand( { geoNear: "places", near: [ 121.4905, 31.2646 ], spherical: true,

 maxDistance:1/6371, num:2 })

{

    "ns" : "mongo_test.places",

    "near" : "1110001100111100001011010110010111001000110011111101",

    "results" : [

        {

            "dis" : 0.00009318095248858048,

            "obj" : {

                "_id" : 115,

                "coordinate" : {

                    "longitude" : 121.4915,

                    "latitude" : 31.25933

                },

                "title" : "仅售148元,市场价298元的星程上服假日酒店全日房一间入住一天,

节假日通用,精致生活,品质享受",

                "address" : "虹口区天水路90号"

            }

        },

        {

            "dis" : 0.00010610660597329082,

            "obj" : {

                "_id" : 465,

                "coordinate" : {

                    "longitude" : 121.48406,

                    "latitude" : 31.26202

                },

                "title" : "【四川北路】热烈庆祝康骏会馆成立8周年!仅售169元!市场价399元的

康骏会馆四川北路一店(仅限3星级技师)全身精油按摩一人次!全程约90分钟!

男女不限!仅限四川北路一店使用,非本市所有门店通用!拉手券消费仅限每日19:00前!

健康有道,骏越万里!",

                "address" : "虹口区四川北路1896号-1904号201室"

            }

        }

    ],

    "stats" : {

        "time" : 0,

        "btreelocs" : 0,

        "nscanned" : 18,

        "objectsLoaded" : 12,

        "avgDistance" : 0.00009964377923093564,

        "maxDistance" : 0.0001064199324957278

    },

    "ok" : 1

}

可以看到返回了很多详细信息,如查询时间、返回数量、最大距离、平均距离等。

另外,results里面直接返回了距离目标点的距离dis。

Symfony2演示代码:

/**

 * @Route("/distance", name="distance")

 * @Template()

 */

public function distanceAction(){

    $longitude = (float)$this->getRequest()->get('lon',121.4905);

    $latitude = (float)$this->getRequest()->get('lat',31.2646);

    //2km

    $max = (float)$this->getRequest()->get('max', 2);

    $places = $this->getPlaceRepository()->createQueryBuilder()

        ->field('coordinate')

        ->geoNear($longitude, $latitude)

        ->spherical(true)

        ->distanceMultiplier(6371)

        ->maxDistance($max/6371)

        ->limit(100)

        ->getQuery()

        ->execute()

        ->toArray();

    return compact('places','longitude', 'latitude', 'max');

}

 

3

站心网

MongoDB下载地址 http://www.mongodb.org/downloads .NET驱动 https://github.com/mongodb/mongo-cshar..

为您推荐

使用 html2canvas 实现截图功能

html2canvas 是一个开源的 JavaScript 库,用于将网页上的 HTML 元素渲染成图像。它通过遍历页面的 DOM 树和计算样式,然后将其绘制到 <canvas> 元素上,最终生成图片。该库不依赖服务器端,而是通过浏览器端的 Java..

使用SuperWebSocket实现Web消息推送

在大部分Web系统中,我们可能遇到需要向客户端推送消息的需求。SuperWebSocket第三方库能让我们轻松的完成任务。SuperWebSocket第三方库可以从网上下载,不过通过Visual Studio Nuget安装更快。引用SuperWebSocket相..

.NET C# 使用Hook钩子实现全局监听键盘和鼠标

C# 是一种面向对象的编程语言,具有丰富的类库和工具支持,适用于各种类型的应用程序开发。Windows 提供了一种称为"钩子"(Hook)的机制,允许拦截并处理系统级别的事件,如键盘按键和鼠标移动。通过结合 C# 和 Hook..

C#使用 Attribute 实现 AOP 功能

在 C# 中,通过自定义 Attribute 并结合一些技术(如动态代理、反射等)可以实现 AOP(面向切面编程)。AOP 通常用于日志记录、性能监控、权限验证等横切关注点。以下是一个使用 C# Attribute 实现 AOP 功能的示例。..

ABP.Net Core使用教程(一)启动模版项目

只需要简单的3步:1,到官网下载模版项目 https://aspnetboilerplate.com/Templates2,用VS2017打开,将Web.Host设置为启动项3,在程序包管理器控制台(Nuget控制台)里设定默认项目为EntityFrameworkCore,执行命令..

C#中的线程安全的集合ConcurrentQueue使用示例

在多线程编程中,如何安全地在不同线程之间共享数据是一个非常重要的问题。C# 为我们提供了一些专门设计的线程安全集合,其中之一就是 ConcurrentQueue<T>。它是一种先进先出(FIFO)的数据结构,专门为多线程环境设..

CSS砌体布局示例和使用场景

CSS砌体布局(Masonry Layout)CSS砌体布局是一种网页布局技术,它的灵感来源于砖石墙的排列方式,类似于“拼图”或“拼砖”的效果。在砌体布局中,元素的排列并不完全遵循传统的网格布局规则,..

使用CSS columns-visibility实现砌体布局

CSS的 columns 属性(如 columns、column-count 和 column-width)通常用于多列文本布局,而不是直接用于砌体布局。然而,结合 columns 和 visibility 属性,可以在某些情况下实现类似砌体布局的效果,虽然它并不完..

使用System.Linq.Dynamic.Core扩展库动态构建 LINQ 查询

System.Linq.Dynamic.Core 是一个扩展库,用于在运行时动态构建 LINQ 查询,支持字符串形式的表达式解析和动态查询操作。它是 .NET 的一个强大工具,适合处理需要灵活定义查询逻辑的场景,例如动态过滤、排序、投影..

小米开源智能家居平台 ha_xiaomi_home 使用示例

小米近期在 GitHub 上开源了名为“ha_xiaomi_home”的项目,即 Home Assistant 米家集成组件。该组件由小米官方支持,旨在让用户在 Home Assistant 中集成和控制小米 IoT 智能设备。主要特点:官方支持:..

前端开发必备网站

1.MDN开发者文档网址:https://developer.mozilla.org/zh-CN/2.CSS教程:https://www.schoolw3c.com/html-css/css/3.node中文网:http://cnodejs.org/getstart4.JavaScript教程网:https://zh.javascript.info/5.web开..

C#13新特性 使用System.Threading.Lock简化线程同步

C# 13 引入了新的线程同步类型 System.Threading.Lock,它通过作用域管理的方式简化了锁的使用,使代码更加清晰可靠。本文将全面介绍 System.Threading.Lock 的功能、适用场景,并提供完整的运行示例程序。1. 什么是..

微软官方Microsoft.Extensions.AI库使用示例

Microsoft.Extensions.AI 库介绍Microsoft.Extensions.AI 是一个扩展库,用于在 .NET 应用程序中轻松集成人工智能(AI)服务,例如 OpenAI、Azure OpenAI 和其他支持文本生成或语言模型的 API。通过与 Microsoft.Ext..

.Net Core中Dapper的使用详解

1.安装Dapper这里直接使用Nuget安装。安装版本是1.50.5安装完成之后,发现Nuget下已经有了Dapper。2.创建DapperHelper接下来创建一个DapperHelper帮助类,来进行读取数据库连接字符串,打开数据库等操作。public cla..

最新CentOS7安装搭建shadowsocks服务端+客户端使用图文教程

使用的CentOS版本是7.9,其他版本也可以。超级推荐的是搭建shadowsocks服务端,安装配置都很简单,几分钟就搞定,客户端支持PC移动端,下面是安装shadowsocks的过程,只要复制粘贴命令就行了,文件夹路径都不需要改..

ASP.NET 使用Entity Framework (EF) 创建迁移修改SQLite数据库表结构

在 ASP.NET 中,使用 Entity Framework (EF) 创建并连接 SQLite 数据库是一种轻量级、高效的数据库管理方式。以下是详细步骤:安装必要的 NuGet 包安装EntityFrameworkCore.Sqlite包:Install-Package Microsoft.Ent..

如何优化ASP.NET Core应用的性能?

优化ASP.NET Core应用性能需要从代码、数据库、配置、服务器和部署等多个层面进行综合考虑。以下是一些优化ASP.NET Core应用性能的关键方法和技巧:1. 代码级优化使用异步编程:避免阻塞线程,通过async和await处理I..

10款.NET开发中推荐的代码分析和质量工具

以下是10款.NET开发中常用的代码分析和质量工具列表,以及它们的主要功能和使用场景:1. SonarQube简介:一个流行的开源静态代码分析平台,用于检测代码中的漏洞、错误、技术债务等问题。主要功能:支持代码质量监测..

在Docker、Kubernetes环境下部署.NET应用的最佳实践

在 Docker 和 Kubernetes 环境中部署 .NET 应用是现代云原生开发的重要实践之一。以下是一些经过验证的最佳实践,涵盖 Docker 镜像优化、Kubernetes 部署配置和整体架构建议。1. Docker 镜像构建的最佳实践1.1 使用..

.NET 游戏开发框架有哪些?

在游戏开发领域,.NET 框架因其强大的功能和灵活性而广受欢迎。对于希望使用 .NET 进行游戏开发的开发者来说,了解可用的框架是至关重要的。以下是一些流行的 .NET 游戏开发框架:1. Unity: 尽管 Unity 主要使用 C# ..

发表回复

返回顶部