0

Leafletマップで使用するために、Opa アプリケーションにGeoJSONを保存しています。

これまでのところ、 Opa 型から正しい GeoJSON として BSON に変換され、Leaflet JS によって適切に使用される方法で、統合された MongoDB データベースでオブジェクトPointをサポートすることができました。LineString

問題は、JSON フィールドcoordinatesが異なるジオメトリ オブジェクトに対して異なる型を持つことです。点の場合は位置 (数値の配列)、文字列の場合は位置の配列 (数値の配列の配列)、点の配列の配列 (数値の配列の配列の配列) ですMultiLineStrings

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

このため、フィールドに頼ってtype幾何学的オブジェクトを区別することはできません。Opa のドキュメントによると、「合計の複数のケース (つまり、レコード) が同じラベルを共有している場合、このラベルは各ケースで同じタイプでなければなりません。」したがって、レコード タイプを区別するフィールドPointを追加することはできません。LineStringさまざまなタイプが埋め込まれた合計タイプを使用する必要があります。

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のドキュメントによると、コレクションごとに作成できる地理空間インデックスは 1 つだけです。この場合、インデックスを作成できる GeoJSON を正しく保存できます。

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

location.Pointしかし、どちらかまたはlocation.LineString両方ではなく、インデックスを作成できます...

OpaでGeoJSONデータの地理空間インデックスを適切に行うには? DBインターフェースと型システムで可能ですか、それとも制限が多すぎますか? 助けやアドバイスをいただければ幸いです。

4

1 に答える 1

0

MongoDB では、2 つの地理空間インデックスを作成して別々に使用できるようですが、同じクエリで両方を使用することはできません。

入力データの例を考えてみましょう。

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.Pointたりします。location.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 に答える