MongoDB中空间数据的存储和操作
本文使用官方C# Driver,实现在MongoDB中存储,查询空间数据(矢量) 空间数据的存储 本例中,从一个矢量文件(shapefile格式)中读取矢量要素空间信息以及属性表,并写入到MongoDB中去,其中读取shapefile文件以及将空间信息转成json的功能通过Ogr库实现 [csh
本文使用官方C# Driver,实现在MongoDB中存储,查询空间数据(矢量)
空间数据的存储
本例中,从一个矢量文件(shapefile格式)中读取矢量要素空间信息以及属性表,并写入到MongoDB中去,其中读取shapefile文件以及将空间信息转成json的功能通过Ogr库实现
[csharp] view plaincopyprint?01.//打开MongoDB的Collection
02. MongoDatabase db = server.GetDatabase("aa");
03. MongoCollection colSheng = db.GetCollection("sheng");
04. //使用Ogr库打开Shapefile文件
05. DataSource ds = Ogr.Open(@"c:\temp\sheng.shp", 0);
06. Layer lyr = ds.GetLayerByIndex(0);
07. //读取要素数量和字段数量
08. int feaCount = lyr.GetFeatureCount(0);
09. int fieldCount = lyr.GetLayerDefn().GetFieldCount();
10. //读取所有字段名
11. List
12. for (int i = 0; i
13. {
14. fieldNames.Add(lyr.GetLayerDefn().GetFieldDefn(i).GetName());
15. }
16. //循环将所有要素添加到MongoDB中
17. for (int i = 0; i
18. {
19. //使用Ogr库将矢量要素的空间信息转成Json格式
20. Feature fea = lyr.GetFeature(i);
21. Geometry geo = fea.GetGeometryRef();
22. string json = geo.ExportToJson(null);
23.
24. BsonDocument doc = new BsonDocument();
25.
26. //将Json格式的空间信息存到Collection中
27. //BsonValue bs = BsonValue.Create(json); //这种方法是不可以的,添加到库里之后无法使用空间查询语句查询
28. BsonValue bs2 = BsonDocument.Parse(json); //这种方法才是正确的
29. //doc.Add(new BsonElement("geom", bs));
30. doc.Add(new BsonElement("geo",bs2));
31. //通过循环将所有字段的属性信息存入Collection中
32. for (int j = 0; j
33. {
34. string tmpFieldVal = fea.GetFieldAsString(j);
35. doc.Add(new BsonElement(fieldNames[j],tmpFieldVal));
36. }
37. var res = colSheng.Insert
38. }
//打开MongoDB的Collection
MongoDatabase db = server.GetDatabase("aa");
MongoCollection colSheng = db.GetCollection("sheng");
//使用Ogr库打开Shapefile文件
DataSource ds = Ogr.Open(@"c:\temp\sheng.shp", 0);
Layer lyr = ds.GetLayerByIndex(0);
//读取要素数量和字段数量
int feaCount = lyr.GetFeatureCount(0);
int fieldCount = lyr.GetLayerDefn().GetFieldCount();
//读取所有字段名
List
for (int i = 0; i
{
fieldNames.Add(lyr.GetLayerDefn().GetFieldDefn(i).GetName());
}
//循环将所有要素添加到MongoDB中
for (int i = 0; i
{
//使用Ogr库将矢量要素的空间信息转成Json格式
Feature fea = lyr.GetFeature(i);
Geometry geo = fea.GetGeometryRef();
string json = geo.ExportToJson(null);
BsonDocument doc = new BsonDocument();
//将Json格式的空间信息存到Collection中
//BsonValue bs = BsonValue.Create(json); //这种方法是不可以的,添加到库里之后无法使用空间查询语句查询
BsonValue bs2 = BsonDocument.Parse(json); //这种方法才是正确的
//doc.Add(new BsonElement("geom", bs));
doc.Add(new BsonElement("geo",bs2));
//通过循环将所有字段的属性信息存入Collection中
for (int j = 0; j
{
string tmpFieldVal = fea.GetFieldAsString(j);
doc.Add(new BsonElement(fieldNames[j],tmpFieldVal));
}
var res = colSheng.Insert
}
然后,可以查看一下存储到MongoDB中的矢量数据是什么样的
在命令行中输入:
[csharp] view plaincopyprint?01.> db.sheng.find().limit(1)
> db.sheng.find().limit(1)
结果为
[javascript] view plaincopyprint?01.{ "_id" : ObjectId("5371bf4e1dbba31914224563"), "geo" : { "type" : "Polygon", "coordinates" : [ [ [ 89.8496, 14.093 ], [ 90.3933, 14.004 ], [ 90.2708, 13.4708 ], [ 89.7284, 13.5597 ], [ 89.8496, 14.093 ] ] ] }, "pyname" : "sx", "boxtype" : "inter", "date" : "2012/6/5 12:41:42" }
{ "_id" : ObjectId("5371bf4e1dbba31914224563"), "geo" : { "type" : "Polygon", "coordinates" : [ [ [ 89.8496, 14.093 ], [ 90.3933, 14.004 ], [ 90.2708, 13.4708 ], [ 89.7284, 13.5597 ], [ 89.8496, 14.093 ] ] ] }, "pyname" : "sx", "boxtype" : "inter", "date" : "2012/6/5 12:41:42" }
可以看到名称为geo的这个Field,里边存的就是矢量要素的坐标信息
空间查询与空间索引
可用的空间操作包括geointersect,geowithin,near等,参考http://docs.mongodb.org/manual/reference/operator/query-geospatial/
这里使用geointersect为例说明一下:
[csharp] view plaincopyprint?01.//获取Collection
02. MongoDatabase db = server.GetDatabase("aa");
03. MongoCollection colSheng = db.GetCollection("sheng");
04.
05. //定义一个查询框或查询多边形
06. var poly = GeoJson.Polygon
07. GeoJson.Position(100, 20),
08. GeoJson.Position(110, 20),
09. GeoJson.Position(110, 40),
10. GeoJson.Position(100, 40),
11. GeoJson.Position(100, 20));
12. //以这个查询多边形为条件定义一条查询语句
13. var queryFilter2 = Query.GeoIntersects("geo", poly);
14. //进行查询,输出MongoCursor
15. cur = colSheng.FindAs
16. //获取结果
17. var res = cur.ToArray();
18. for (int i = 0; i
19. {
20. BsonDocument tmpDoc = res.ElementAt(i);
21. //do something you want
22. }
//获取Collection
MongoDatabase db = server.GetDatabase("aa");
MongoCollection colSheng = db.GetCollection("sheng");
//定义一个查询框或查询多边形
var poly = GeoJson.Polygon
GeoJson.Position(100, 20),
GeoJson.Position(110, 20),
GeoJson.Position(110, 40),
GeoJson.Position(100, 40),
GeoJson.Position(100, 20));
//以这个查询多边形为条件定义一条查询语句
var queryFilter2 = Query.GeoIntersects("geo", poly);
//进行查询,输出MongoCursor
cur = colSheng.FindAs
//获取结果
var res = cur.ToArray();
for (int i = 0; i
{
BsonDocument tmpDoc = res.ElementAt(i);
//do something you want
}
关于空间索引,可参考http://docs.mongodb.org/manual/applications/geospatial-indexes/
这里不详细说了
空间查询运算的问题:
在使用GeoIntersect进行空间查询时,遇到了查询结果与ArcGIS不一致的情况,详细看了一下,像是MongoDB的一个BUG(目前使用的是2.6.0版本)
具体信息如下(在命令行中操作):
Collection中的坐标
[csharp] view plaincopyprint?01.> db.test.find()
02.{ "_id" : ObjectId("535884771dbba31858ad2101"), "geo" : { "type" : "Polygon", "coordinates" : [ [ [ 96.722, 38.755 ], [ 97.3482, 38.6922 ], [ 97.1674, 38.0752 ], [ 96.5474, 38.1383 ], [ 96.722, 38.755 ] ] ] } }
> db.test.find()
{ "_id" : ObjectId("535884771dbba31858ad2101"), "geo" : { "type" : "Polygon", "coordinates" : [ [ [ 96.722, 38.755 ], [ 97.3482, 38.6922 ], [ 97.1674, 38.0752 ], [ 96.5474, 38.1383 ], [ 96.722, 38.755 ] ] ] } }
使用的查询语句
[csharp] view plaincopyprint?01.> db.test.find({ "geo" : { "$geoIntersects" : { "$geometry" : { "type" : "Polygon", "coordinates" : [[[91.0, 33.0], [102.0, 33.0], [102.0, 38.0], [91.0, 38.0], [91.0, 33.0]]] } } } })
> db.test.find({ "geo" : { "$geoIntersects" : { "$geometry" : { "type" : "Polygon", "coordinates" : [[[91.0, 33.0], [102.0, 33.0], [102.0, 38.0], [91.0, 38.0], [91.0, 33.0]]] } } } })
查询结果:
[csharp] view plaincopyprint?01.{ "_id" : ObjectId("535884771dbba31858ad2101"), "geo" : { "type" : "Polygon", "coordinates" : [ [ [ 96.722, 38.755 ], [ 97.3482, 38.6922 ], [ 97.1674, 38.0752 ], [ 96.5474, 38.1383 ], [ 96.722, 38.755 ] ] ] } }
{ "_id" : ObjectId("535884771dbba31858ad2101"), "geo" : { "type" : "Polygon", "coordinates" : [ [ [ 96.722, 38.755 ], [ 97.3482, 38.6922 ], [ 97.1674, 38.0752 ], [ 96.5474, 38.1383 ], [ 96.722, 38.755 ] ] ] } }
但可以看到,collection中只有一条记录,且该记录所有点的Y坐标均大于38.0,为什么查询结果里,这条记录与语句中的Box相交呢。。。很奇怪
因为有这样的问题,所以还不放心直接将空间查询用于实际应用,而是通过一种变通的方法进行简单的空间查询,测试后发现,可能是由于空间索引的问题,这种方式查询比自带的GeoIntersects方法要快
大致思路为:为每一条记录均生成一个最小外接矩形,得到其xmax,xmin,ymax,ymin四个边界值,用数值的形式保存至Collection中,每次进行空间查询时,首先通过最小外接矩形进行一次筛选,判断这些最小外接矩形与查询语句中多边形的最小外接矩形之间的关系,如果相交,那么进行第二步判断,通过Ogr组件判断实际的多边形是否相交,返回最后结果
首先是生成最小外接矩形的代码:
[csharp] view plaincopyprint?01.//获取Collection
02. MongoDatabase db = server.GetDatabase("aa");
03. MongoCollection colsheng= db.GetCollection("sheng");
04. //查询所有记录
05. var cur = colsheng.FindAllAs
06. long totalCount = cur.Count();
07. //遍历所有记录
08. for (int i = 0; i
09. {
10. if (i * 1000 >= totalCount) continue;
11. int skip = i * 1000;
12. var cur2 = cur.Clone
13. var lst = cur2.ToArray();
14. for (int j = 0; j
15. {
16. //获取一条记录对应的BsonDocument
17. BsonDocument doc = lst[j];
18. var id = doc["_id"]; //该记录对应的ID
19. BsonDocument geo = doc["geo"].ToBsonDocument();
20. string geostr = geo[1].ToString(); //该记录对应空间信息的Json字符串
21. List
22. double xmin = 181, xmax = -181, ymin = 91, ymax = -91; //四个边界值,由于图层为经纬度,所以初值设为这些值
23. //计算最大最小值
24. for (int k = 0; k
25. {
26. if (k % 2 == 0)
27. {
28. if (coords[k]
29. if (coords[k] > xmax) xmax = coords[k];
30. }
31. else
32. {
33. if (coords[k]
34. if (coords[k] > ymax) ymax = coords[k];
35. }
36. }
37. //将最大最小值写入Collection
38. var tmpQuery = Query.EQ("_id", id);
39. var tmpUpdate = MongoDB.Driver.Builders.Update.Set("xmax", xmax);
40. var tmpres = col02c.Update(tmpQuery, tmpUpdate);
41. tmpUpdate = MongoDB.Driver.Builders.Update.Set("xmin", xmin);
42. tmpres = col02c.Update(tmpQuery, tmpUpdate);
43. tmpUpdate = MongoDB.Driver.Builders.Update.Set("ymax", ymax);
44. tmpres = col02c.Update(tmpQuery, tmpUpdate);
45. tmpUpdate = MongoDB.Driver.Builders.Update.Set("ymin", ymin);
46. tmpres = col02c.Update(tmpQuery, tmpUpdate);
47. }
48. }
//获取Collection
MongoDatabase db = server.GetDatabase("aa");
MongoCollection colsheng= db.GetCollection("sheng");
//查询所有记录
var cur = colsheng.FindAllAs
long totalCount = cur.Count();
//遍历所有记录
for (int i = 0; i
{
if (i * 1000 >= totalCount) continue;
int skip = i * 1000;
var cur2 = cur.Clone
var lst = cur2.ToArray();
for (int j = 0; j
{
//获取一条记录对应的BsonDocument
BsonDocument doc = lst[j];
var id = doc["_id"]; //该记录对应的ID
BsonDocument geo = doc["geo"].ToBsonDocument();
string geostr = geo[1].ToString(); //该记录对应空间信息的Json字符串
List
double xmin = 181, xmax = -181, ymin = 91, ymax = -91; //四个边界值,由于图层为经纬度,所以初值设为这些值
//计算最大最小值
for (int k = 0; k
{
if (k % 2 == 0)
{
if (coords[k]
if (coords[k] > xmax) xmax = coords[k];
}
else
{
if (coords[k]
if (coords[k] > ymax) ymax = coords[k];
}
}
//将最大最小值写入Collection
var tmpQuery = Query.EQ("_id", id);
var tmpUpdate = MongoDB.Driver.Builders.Update.Set("xmax", xmax);
var tmpres = col02c.Update(tmpQuery, tmpUpdate);
tmpUpdate = MongoDB.Driver.Builders.Update.Set("xmin", xmin);
tmpres = col02c.Update(tmpQuery, tmpUpdate);
tmpUpdate = MongoDB.Driver.Builders.Update.Set("ymax", ymax);
tmpres = col02c.Update(tmpQuery, tmpUpdate);
tmpUpdate = MongoDB.Driver.Builders.Update.Set("ymin", ymin);
tmpres = col02c.Update(tmpQuery, tmpUpdate);
}
}
然后是查询的代码:
[csharp] view plaincopyprint?01.//获取Collection
02. MongoDatabase db = server.GetDatabase("aa");
03. MongoCollection colSheng = db.GetCollection("zy02c");
04. //第一步,通过四边界筛选,
05. var query = Query.And(Query.GT("xmax", 91.0), Query.LT("xmin", 102.0), Query.GT("ymax", 33.0), Query.LT("ymin", 38.0));
06. var cur = colSheng.FindAs
07. //定义第二空间运算时的条件多边形(Ogr格式的定义)
08. Geometry queryGeoLR = new Geometry(wkbGeometryType.wkbLinearRing);
09. queryGeoLR.AddPoint(91.0, 33.0,0);
10. queryGeoLR.AddPoint(102.0, 33.0,0);
11. queryGeoLR.AddPoint(102.0, 38.0,0);
12. queryGeoLR.AddPoint(91.0, 38.0,0);
13. queryGeoLR.AddPoint(91.0, 33.0,0);
14. Geometry queryGeo = new Geometry(wkbGeometryType.wkbPolygon);
15. queryGeo.AddGeometry(queryGeoLR);
16. //循环查询到的结果
17. var lst = cur.ToArray();
18. for (int i = lst.Length-1; i >=0; i--)
19. {
20. //获取当前记录对应的BsonDocument
21. BsonDocument doc = lst[i];
22. var id = doc["_id"]; //当前记录的ID
23. BsonDocument geo = doc["geo"].ToBsonDocument();
24. string geostr = geo[1].ToString(); //当前记录对应空间信息的Json字符串
25.
26. //通过Json串获取坐标值,并生成对应的Geometry对象
27. List
28. Geometry resGeoLR = new Geometry(wkbGeometryType.wkbLinearRing);
29. for (int j = 0; j
30. {
31. resGeoLR.AddPoint_2D(coords[j], coords[j + 1]);
32. }
33. resGeoLR.AddPoint_2D(coords[0], coords[1]);
34. Geometry resGeo = new Geometry(wkbGeometryType.wkbPolygon);
35. resGeo.AddGeometry(resGeoLR);
36. //判断是该Geometry与条件多边形是否相交
37. if (resGeo.Intersects(queryGeo))
38. {
39. //do something
40. }
41. }

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

热门话题

在iPhone上面临滞后,缓慢的移动数据连接?通常,手机上蜂窝互联网的强度取决于几个因素,例如区域、蜂窝网络类型、漫游类型等。您可以采取一些措施来获得更快、更可靠的蜂窝互联网连接。修复1–强制重启iPhone有时,强制重启设备只会重置许多内容,包括蜂窝网络连接。步骤1–只需按一次音量调高键并松开即可。接下来,按降低音量键并再次释放它。步骤2–该过程的下一部分是按住右侧的按钮。让iPhone完成重启。启用蜂窝数据并检查网络速度。再次检查修复2–更改数据模式虽然5G提供了更好的网络速度,但在信号较弱

Node.js 是一种服务器端 JavaScript 运行时,而 Vue.js 是一个客户端 JavaScript 框架,用于创建交互式用户界面。Node.js 用于服务器端开发,如后端服务 API 开发和数据处理,而 Vue.js 用于客户端开发,如单页面应用程序和响应式用户界面。

哭死啊,全球狂炼大模型,一互联网的数据不够用,根本不够用。训练模型搞得跟《饥饿游戏》似的,全球AI研究者,都在苦恼怎么才能喂饱这群数据大胃王。尤其在多模态任务中,这一问题尤为突出。一筹莫展之际,来自人大系的初创团队,用自家的新模型,率先在国内把“模型生成数据自己喂自己”变成了现实。而且还是理解侧和生成侧双管齐下,两侧都能生成高质量、多模态的新数据,对模型本身进行数据反哺。模型是啥?中关村论坛上刚刚露面的多模态大模型Awaker1.0。团队是谁?智子引擎。由人大高瓴人工智能学院博士生高一钊创立,高

MetaMask(中文也叫小狐狸钱包)是一款免费的、广受好评的加密钱包软件。目前,BTCC已支持绑定MetaMask钱包,绑定后可使用MetaMask钱包进行快速登入,储值、买币等,且首次绑定还可获得20USDT体验金。在BTCCMetaMask钱包教学中,我们将详细介绍如何注册和使用MetaMask,以及如何在BTCC绑定并使用小狐狸钱包。MetaMask钱包是什么?MetaMask小狐狸钱包拥有超过3,000万用户,是当今最受欢迎的加密货币钱包之一。它可免费使用,可作为扩充功能安装在网络

最近,军事圈被这个消息刷屏了:美军的战斗机,已经能由AI完成全自动空战了。是的,就在最近,美军的AI战斗机首次公开,揭开了神秘面纱。这架战斗机的全名是可变稳定性飞行模拟器测试飞机(VISTA),由美空军部长亲自搭乘,模拟了一对一的空战。5月2日,美国空军部长FrankKendall在Edwards空军基地驾驶X-62AVISTA升空注意,在一小时的飞行中,所有飞行动作都由AI自主完成!Kendall表示——在过去的几十年中,我们一直在思考自主空对空作战的无限潜力,但它始终显得遥不可及。然而如今,

特斯拉机器人Optimus最新视频出炉,已经可以在厂子里打工了。正常速度下,它分拣电池(特斯拉的4680电池)是这样的:官方还放出了20倍速下的样子——在小小的“工位”上,拣啊拣啊拣:这次放出的视频亮点之一在于Optimus在厂子里完成这项工作,是完全自主的,全程没有人为的干预。并且在Optimus的视角之下,它还可以把放歪了的电池重新捡起来放置,主打一个自动纠错:对于Optimus的手,英伟达科学家JimFan给出了高度的评价:Optimus的手是全球五指机器人里最灵巧的之一。它的手不仅有触觉

FP8和更低的浮点数量化精度,不再是H100的“专利”了!老黄想让大家用INT8/INT4,微软DeepSpeed团队在没有英伟达官方支持的条件下,硬生生在A100上跑起FP6。测试结果表明,新方法TC-FPx在A100上的FP6量化,速度接近甚至偶尔超过INT4,而且拥有比后者更高的精度。在此基础之上,还有端到端的大模型支持,目前已经开源并集成到了DeepSpeed等深度学习推理框架中。这一成果对大模型的加速效果也是立竿见影——在这种框架下用单卡跑Llama,吞吐量比双卡还要高2.65倍。一名

2024QS世界大学学科排名来了!总体和23年变化不大。根据官网信息,2024QS世界大学学科排名涵盖了55个细分学科和5大学术领域。共有1559所高校参与了排名,其中64所高校是今年的新面孔(也就是说2023年的排名中没有出现)。而在这64所高校中,又有14所是真真正正第一次出现的。其中就包含了中国科学院大学。据精分学科来说,音乐(Music)是今年推出的新科目。此外,数据科学和人工智能排名得到了扩充,排名新加入了51所高校。总榜排名总榜前五名分别是:麻省理工学院、剑桥大学、牛津大学、哈佛大学
