0

我将GeoJSON存储在 Opa 应用程序中以用于Leaflet地图。

到目前为止,我设法支持集成 MongoDB 数据库中PointLineString对象,方法是将它从 Opa 类型转换为 BSON 作为正确的 GeoJSON,并由 Leaflet JS 正确使用。

问题是 JSON 字段coordinates对于不同的几何对象有不同的类型。它是点的位置(数字数组)或字符串的位置数组(数字数组的数组),点数组的数组(数字数组的数组)MultiLineStrings

{ type: "Point", coordinates: [102.0, 0.5] }
{ type: "LineString", "coordinates": [[102.0, 0.0], [103.0, 1.0]] }
...

出于这个原因,我不能依靠type场来区分几何对象。根据Opa 文档:“如果一个总和的多个案例(即记录)共享相同的标签,则此标签在每个案例中必须具有相同的类型。” 所以,我不能只添加字段PointLineString区分记录类型。我必须使用嵌入不同类型的 sum 类型:

type Article.geo_json_point =
  {
    string `type`,
    list(float) coordinates,
  };
type Article.geo_json_multipoint =
  {
    string `type`,
    list(list(float)) coordinates,
  };
type Article.geo_json =
  { Article.geo_json_point Point } or
  { Article.geo_json_multipoint LineString } or
  { Null };

type Article.t = {
  Article.id id,
  Article.geo_json location,
  ... // some other fields
};
database mydb {
  Article.t /article[{id}]
  /article[_]/location = {Null}
  /article[_]/location/Point/`type` = "Point"
  /article[_]/location/LineString/`type` = "LineString"
}

根据 MongoDB文档,每个集合只能创建一个地理空间索引。在这种情况下,我可以正确存储可以索引的 GeoJSON:

$ mongo mydb
> db.article.findOne({}, {_id:0, location:1})
{
    "location" : {
            "Point" : {
                    "type" : "Point",
                    "coordinates" : [
                            18.089788,
                            51.762638
                    ]
            }
    }
}

但我可以索引一个location.Pointlocation.LineString但不能同时索引...

如何在 Opa 中正确执行 GeoJSON 数据的地理空间索引?它的 DB 接口和类型系统是否可行,还是限制太多?我感谢任何帮助或建议!

4

1 回答 1

0

似乎 MongoDB 允许创建两个地理空间索引并分别使用它们,但不能在同一个查询中同时使用它们。

考虑示例输入数据:

db.geo.insert({location: {Point: {type: "Point", coordinates: [15,15]}}});
db.geo.insert({location: {LineString: {type: "LineString", coordinates: [[12,12],[13,13]]}}});
db.geo.insert({location: {Point: {type: "Point", coordinates: [55,55]}}});
db.geo.insert({location: {LineString: {type: "LineString", coordinates: [[52,52],[53,53]]}}});

和索引:

db.geo.ensureIndex({"location.Point": "2dsphere"});
db.geo.ensureIndex({"location.LineString": "2dsphere"});

该字段的地理空间查询location

db.geo.find({"location": {$geoWithin: {$geometry: {type: "Polygon", coordinates: [[[10,10],[10,20],[20,20],[20,10],[10,10]]]}}}});

给出正确的结果,但不使用索引:(

幸运的是,查询location.Pointlocation.LineString使用索引:

> [...].explain()
{
    "cursor" : "S2Cursor",
    "isMultiKey" : true,
    "n" : 1,
    "nscannedObjects" : 1,
    [...]
    "matchTested" : NumberLong(1),
    "geoTested" : NumberLong(1),
    "cellsInCover" : NumberLong(25),
    [...]
}

不幸的是,Mongo 不允许{$or: [subquery1, subquery2]}用于“特殊”查询......因此,这并不能轻松解决问题,但可以在应用程序级别解决它。

于 2013-09-20T12:10:06.000 回答