MongoDB предлагает новые геопространственные функции в версиях 2.4 и 2.6. Основой этих функций является введение GeoJSON , формата с открытым исходным кодом для богатых геопространственных типов, которые выходят за рамки того, что MongoDB поддерживал в предыдущих версиях.
Этот пост является учебником для начинающих разработчиков геопространственных данных в MongoDB. Мы стремимся познакомить вас с основами геопространства в MongoDB и помочь вам получить максимальную отдачу от ваших данных.
Краткое слово о предыдущих версиях MongoDB (<2.4)
В прошлом геопространственные объекты MongoDB использовали координаты, сохраненные в форме пары координат долгота / широта. Пользователи будут хранить пару координат в поле местоположения в документе. В документации MongoDB этот формат теперь называется «устаревшими парами координат».
{ name : "Timmy's Taco Truck", loc : [ 37.7577 , -122.4376 ] }
Коллекция документов с устаревшими парами координат представляет собой поле точек.
Используя геопространственный (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. Наше поле точек теперь может выглядеть так:
- Используйте данные 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