Статьи

Учебник по геопространственным данным и MongoDB

MongoDB предлагает новые геопространственные функции в версиях 2.4 и 2.6. Основой этих функций является введение GeoJSON , формата с открытым исходным кодом для богатых геопространственных типов, которые выходят за рамки того, что MongoDB поддерживал в предыдущих версиях.

Этот пост является учебником для начинающих разработчиков геопространственных данных в MongoDB. Мы стремимся познакомить вас с основами геопространства в MongoDB и помочь вам получить максимальную отдачу от ваших данных.

Краткое слово о предыдущих версиях MongoDB (<2.4)

В прошлом геопространственные объекты MongoDB использовали координаты, сохраненные в форме пары координат долгота / широта. Пользователи будут хранить пару координат в поле местоположения в документе. В документации MongoDB этот формат теперь называется «устаревшими парами координат».

{
  name : "Timmy's Taco Truck",
  loc : [ 37.7577 , -122.4376 ]
}

Коллекция документов с устаревшими парами координат представляет собой поле точек.

MongoDB Legacy Coordinates

Используя геопространственный (2d) индекс, эти точки запрашивались двумя способами:

  • Близость — чтобы определить набор точек вблизи точки или в пределах определенного расстояния от точки, пользователи предоставили другую пару координат в своих геопространственных запросах. Например:
db.places.find( { loc : 
                  { $near : [ 100 , 100 ],
                    $maxDistance: 10 }
                } )
  • Включение. Чтобы определить, находится ли какая-либо из сохраненных точек в указанной области, пользователи предоставили в своих запросах специальные операторы MongoDB, такие как $ box и $ polygon . Например:
db.places.find( { loc : 
                  { $geoWithin : 
                    { $polygon : 
                      [ [ 0 , 0 ] , [ 0 , 1 ] , [ 1 , 1 ] , [ 1 , 0 ] ] 
                 } } } )

Начиная с MongoDB 2.4, геопространственные запросы больше не используют специфичные для MongoDB операторы форм, такие как $ box или $ polygon, как часть геопространственных запросов. Хотя вы все еще можете хранить и запрашивать устаревшие пары координат, в геопространственных запросах теперь используется GeoJSON.

Представляем GeoJSON

GeoJSON — это спецификация с открытым исходным кодом для JSON-форматирования фигур в координатном пространстве. Спецификация GeoJSON используется в геопространственном сообществе, и растет поддержка библиотек на большинстве популярных языков. В соответствии с открытым стандартом MongoDB стремится облегчить разработчикам работу с уже имеющимися данными.

Возможно, лучший способ понять GeoJSON — это увидеть его. В следующем примере показан синтаксис для представления точки и многоугольника.

// Point representation of Timmy's Taco Truck
{
  name : "Timmy's Taco Truck",
  loc : {
    type : "Point",
    coordinates : [ 37.7577 , -122.4376 ]
  }
}
 
// Polygon representation (Square) of a Food Truck Park
{
  name: "Truckapalooza Square",
  loc : {
    type : "Polygon",
    coordinates : [ [ [ 0 , 0 ] , [ 0 , 1 ] , [ 1 , 1 ] , [  1 , 0 ] , [ 0 , 0 ] ] ]
  }
}

Каждый документ GeoJSON (или поддокумент) обычно состоит из двух полей:

  • type — представляемая форма, которая сообщает читателю GeoJSON, как интерпретировать поле «координаты»
  • координаты — массив точек, конкретное расположение которых определяется полем «тип»

Теперь, когда MongoDB поддерживает GeoJSON, пользователи могут:

  • Храните гораздо более богатые данные. Начиная с версии 2.6, вы можете хранить и индексировать следующие типы GeoJSON: Point, LineString, Polygon, MultiPoint, MultiLineString, MultiPolygon и GeometryCollection. Наше поле точек теперь может выглядеть так:MongoDB GeoJSON
  • Используйте данные GeoJSON взаимозаменяемо в обоих документах и ​​запросах. Предоставляя компонент геометрии GeoJSON в универсальном специальном операторе MongoDB $ geometry , можно избежать произвольного синтаксиса запроса. Давайте вернемся к нашему предыдущему примеру поиска точек в квадрате, но на этот раз с помощью GeoJSON:
db.places.find( { loc : 
                  { $geoWithin : 
                    { $geometry : 
                      { type : "Polygon",
                        coordinates : [ [ [ 0 , 0 ] , [ 0 , 1 ] , [ 1 , 1 ] , [ 1 , 0 ] , [ 0 , 0 ] ] ]
                } } } } )

 

  • Используйте совершенно новые функции. Например, $ geoIntersects возвращает все местоположения — точки и фигуры — которые пересекаются с точкой или формой GeoJSON. Эта операция «дай мне формы, которые пересекают эту форму» — это то, что ты не мог сделать раньше.

Если вы заинтересованы в участии в сообществе GeoJSON, вы можете подписаться и внести свой вклад через этот список обсуждений GeoJSON .

Геопространственные индексы

В MongoDB есть три вида геопространственных индексов . Обратитесь к матрице совместимости запросов, приведенной в документации MongoDB, для получения конкретной информации о том, как работает каждый тип запроса для каждого типа индекса. В общем:

  • 2d — эти индексы поддерживают устаревшие данные пары координат и допускают запросы старой формы того типа, который мы обсуждали выше (например, $ geoWithin с использованием синтаксиса $ box или $ polygon). Двухмерные индексы не поддерживают запросы в формате GeoJSON или значения данных GeoJSON. Также важно отметить, что двумерные индексы работают с плоской геометрией, поэтому на стороне клиента могут потребоваться некоторые усилия, чтобы результаты их запросов отражали реальные геопространственные данные.
  • 2dsphere — этот новый тип индекса поддерживает запросы GeoJSON и значения данных GeoJSON, а также поддерживает устаревшие пары координат в значениях данных. Это означает, что если вы создаете индекс 2dsphere для поля с форматированием устаревших пар, вы все равно можете использовать форматы запросов GeoJSON. Однако вы не можете делать запросы, используя устаревшие пары.
  • geoHaystack — этот индекс оптимизирован для поиска в небольших областях и может использоваться только с помощью команды базы данных geoSearch. Мы не обсуждаем стоге сена в этом блоге, но вы можете прочитать больше об этом здесь .

Некоторые геопространственные советы

Количество геопространственных индексов

Вы можете иметь несколько геопространственных индексов для каждой коллекции, если только вы не используете команду базы данных geoNear и / или оператор конвейера агрегации $ geoNear. Читайте об этих соображениях здесь .

Импорт CSV-геопространственных данных

Инструмент mongoimport не поддерживает расширенные данные, такие как массивы и вложенные документы. Следовательно, mongoimport не поддерживает чтение геопространственных данных. В качестве обходного пути мы предлагаем преобразовать CSV в JSON, который является лучшим форматом для импорта геопространственных данных. Один такой конвертер можно найти в этом репо .

Форматирование многоугольника

Одним из аспектов GeoJSON, который легко пропустить при начале работы, является правильное форматирование полигонов: последняя предоставленная пара координат должна быть такой же, как и первая, для создания замкнутой фигуры .

//Invalid - Each point/vertex of the polygon is provided.
{ "type": "Polygon",
    "coordinates": [
      [ [ 100.0 , 0.0 ] , [ 101.0 , 0.0 ] , [ 101.0 , 1.0 ] , [ 100.0 , 1.0 ] ] 
    ]
}
 
//Valid - First vertex of the polygon is provided at both the beginning and end of a LinearRing.
{ "type": "Polygon",
    "coordinates": [
      [ [ 100.0 , 0.0 ] , [ 101.0 , 0.0 ] , [ 101.0 , 1.0 ] , [ 100.0 , 1.0 ] , [ 100.0 , 0.0 ] ]
    ]
}

Для получения дополнительной информации о том, как форматировать полигоны, обратитесь к документации GeoJSON Polygon и   LinearRing .

Собственные библиотеки GeoJSON

Многие языки имеют собственные библиотеки, которые облегчают работу с данными GeoJSON. Например, в Python есть библиотека « geojson », которая содержит классы для всех объектов GeoJSON и функции для простого создания, кодирования и декодирования объектов GeoJSON.

Единицы для расчета запроса

Единицы, используемые для расчета результатов запроса, различаются в зависимости от индекса и типа запроса. В случае сомнений обращайтесь к геопространственной матрице MongoDB .

Это обычно относится к оператору $ maxDistance . Оператор ограничивает запрос $ near, чтобы он возвращал только те документы, которые находятся на максимальном расстоянии от точки. Если вы запрашиваете точку GeoJSON, укажите $ maxDistance в метрах. Если вы запрашиваете устаревшие пары координат, укажите $ maxDistance в радианах .

Спасибо за чтение!

Существует масса геопространственных данных, ожидающих разработки и анализа новыми разработчиками. Мы надеемся, что этот пост станет хорошей отправной точкой для работы с геопространственными данными в MongoDB. Если вам нужна помощь в работе с геопространственными данными в MongoLab, вы можете связаться с нашей командой по адресу [email protected] в любое время.

Счастливого взлома!

Крис и Эрик @ MongoLab