2013-09-19 3 views
0

Я сохраняю GeoJSON в приложении Opa для использования с Leaflet.Индексирование данных GeoJSON в MongoDB для Opa

До сих пор мне удалось поддерживать Point и LineString объекты в интегрированной базе данных MongoDB в том, что он переводится на в BSON от типа Opa в правильном GeoJSON и используется должным образом используемый Листовка JS.

Проблема в том, что поле JSON coordinates имеет различный тип для разных геометрических объектов. Это положение (массив чисел) для точек или массив позиций (массив массива чисел) для строки, массив массива точек (массив массива массива чисел) для MultiLineStrings:

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

Для этого Я не могу полагаться на поле type, чтобы отличить геометрические объекты. Согласно Opa documentation: «если несколько случаев (т. Е. Записи) содержат одну и ту же метку, эта метка должна иметь один и тот же тип в каждом случае». Поэтому я не могу просто добавить поля 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 documentation вы можете создать только один геопространственной индекс для каждого семейства. В этом случае я могу правильно хранить в формате GeoJSON, которые могут быть проиндексированы:

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

но может индексировать либо location.Point или location.LineString, но не оба ...

Как правильно сделать геопространственной inxeding данных GeoJSON в Opa? Возможно ли это с его интерфейсом DB и системой типа, или это слишком ограничивает? Я ценю любую помощь или совет!

ответ

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.Point или location.LineString использует индекс:

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

К сожалению, Монго не позволить использовать {$or: [subquery1, subquery2]} для «особых» запросов ... Таким образом, это не решает проблему легко, но это может быть обманутым на уровне приложений.

Смежные вопросы