Работа с геоданными в MongoDb
Марк Заславский, mark.zaslavskiy@gmail.com
О чем будет доклад
● Обзор:
– Короткое знакомство с Mongo
– Коротко про GeoJson
– Какие данные можно хранить в Mongo
– Как хранить геоданные в Mongo
– Как индексировать геоданные
– Как выполнять запросы к данным (поиск объектов
рядом/внутри/на пересечении с областями)
● Примеры использования геовозможностей
MongoDb в Geo2Tag
Примеры к докладу
● Ссылка для скачивания:
http://bit.ly/1OHMY0N
● В архиве текстовые файлы со
списками комманд для каждого
примера
● Решетки (#) это не комментарий в
Mongo, их нужно удалить
● Примеры проверялись на MongoDb
2.4.9
(Вопросы в зал)
Введение и мотивация
● Геоданные:
– часто (но не всегда) = bigdata,
– имеют сложные алгоритмы анализа/обработки,
– могут иметь сложную структуру (границы областей,
маршруты).
● Mongo
– из коробки умеет работать с геоданными,
– хорошо масштабируется,
– представление геоданных стандартизовано
(GeoJSON).
Короткое введние в Mongo
● MongoDb – документо-
ориентированная СУБД
● Данные хранятся в BSON (почти
JSON)
● Документы объединяются в
коллекции
● У коллекций нет обязательной
схемы
● MapReduce
● Полнотекстовый поиск
Коллекции и документы
● Примерное соответствие с
SQL СУБД:
– Коллекция = таблица
– Документ = запись в таблице
– Идентификатор _id
(обязательное поле документа)
= первичный ключ
● Коллекции и базы данных
создаются “ленивым
образом”
Пример CRUD 1mongo_crud.txt
$ mongo test_db
> db.test_collection.insert({key1:'val1', key2:'val2'})
> db.test_collection.insert({key3:'val3'})
> db.test_collection.find({key3:'val3'})
> db.test_collection.find()
> db.test_collection.remove({key3:'val3'})
> db.test_collection.find()
> db.test_collection.update({ "key1" : "val1", "key2" :
"val2" }, {$set: {"key1" : "val2"}})
Формат GeoJSON
● Надмножество JSON для хранения точек,
ломаных и многоугольников (а также их
совокупностей (гладких кривых нет:)).
● Не накладывает ограничение на тип
координат (плоские, сферические,
параболические ...).
● Координаты точки задаются в виде массива
[x , y]
Или
[долгота, широта]
Наглядные примеры
● https://ru.wikipedia.org/wiki/GeoJSON#.D0.9E.D0.B1.D1.8A.D0.B5.D0.BA.D1.82.D1.8B
Наглядные примеры
● https://ru.wikipedia.org/wiki/GeoJSON#.D0.9E.D0.B1.D1.8A.D0.B5.D0.BA.D1.82.D1.8B
GeoJSON - инструменты
● Генерация GeoJSON по карте -
http://geojson.io/
● Валидатор - http://geojsonlint.com/
● Бьютификатор -
https://jsonformatter.curiousconcept.c
om/
● Описание стандарта –
http://geojson.org/
Как сохранить геоданные в БД
● Форматы:
– legacy coordinate pairs
(только точки) [x,y]
– GeoJson (точки, линии,
полигоны ...)
● Нет контроля типов у
полей координат
● Одно поле = один формат
представления
● Можно сохранять как в
отдельное поле, так и во
вложенное
Сохранение геоданных в БД –
пример 2location_writing.txt
$ mongo test_db
> db.test_collection1.insert({
name: '1',
location : {
"type" : "Point",
"coordinates" : [ 1.0, 1.0 ]
}
})
> db.test_collection2.insert({
name: '2',
location : [ 1.0, 1.0 ]
})
Пространственные индексы -
преамбула
● Индексы – ускорение запросов.
● Разные геометрии:
– Плоская (евклидово расстояние)
– Сферическая WGS84,
http://spatialreference.org/ref/epsg/4326/)
http://www.colorado.edu/geography/gcraft/notes/datum/gif/geoid2.gif
Пространственные индексы
● 2dsphere
– Сферическая геометрия, GeoJSON или legacy
coordinate pairs
– Можно делать связанный индекс с несколькими
полями
● 2d
– Плоская геометрия, legacy coordinate pairs
– Связанный индекс только с одним полем
● geoHaystack
– 2d + одно не геополе, быстрее на малых площадях
чем 2d
Пример - Создаем индекс
3indexes_creation.txt
> db.test_collection1.createIndex({
location: '2dsphere'})
> db.test_collection2.createIndex({
location: '2d'})
# Проверяем индексы
> db.system.indexes.find()
$geoWithin и $geoIntersects
● Что это:
– Критерии для поиска (могут быть частью сложного
запроса)
– Поиск либо объектов внутри (geoWithin), либо на
пересечении с областью (geoIntersects)
– Работает для всех геометрий и типов задания
координат
● Особенности
– Индекс не нужен
– Есть проблема с ооочень большими областями
фильтрации
$geoWithin и $geoIntersects
● Что приходит в ответ - список документов
без сортировки
● Как можно искать:
– Сферическая геометрия: $geometry,
$centerSphere
– Плоская геометрия: $box, $polygon, $center
Пример про $geoWithin
4geowithin.txt
db.test_collection1.find( { location :
{ $geoWithin :
{ $geometry :
{ type : "Polygon" ,
coordinates : [ [
[ 0 , 0 ] ,
[ 3 , 6 ] ,
[ 6 , 1 ] ,
[ 0 , 0 ] # Замыкаем фигуру
] ]
} } } } )
Пример про $geoWithin
4geowithin.txt
db.test_collection1.find( { location :
{ $geoWithin :
{ $centerSphere:
[ [1, 1], # Центр
2] # Радиус в радианах
}}})
Пример про $geoIntersects
4geointersects.txt
db.test_collection1.find( { location :
{ $geoIntersects :
{$geometry:
{"type": "LineString",
"coordinates": [ [0, 1], [1, 1] ]
}
}
}
})
$near и $nearSphere
● Что это: операторы поиска объектов, близких к
точке.
● Особенности
– Near – использует евклидово расстояние,
nearSphere – сферическое.
– Требует наличия любого геоиндекса.
– Нельзя комбинировать со сложными запросами,
требующими специальный индекс
– Можно задать пределы расстояний.
$near и $nearSphere
● Что приходит в ответ: отсортированные по
расстоянию документы
● Единицы измерения расстояний зависят от
того, как задана точка отсчета:
– GeoJSON – метры
– Legacy pair - радианы
Пример - поиск точек по
расстоянию 5nearsphere.txt
db.test_collection1.find( { location :
{ $nearSphere:
{ $geometry :
{ type : "Point",
coordinates : [ 0, 0 ]}, # Точка отсчета
$maxDistance : 190000} # В метрах
}
})
Операции аггрегирования
● примерный аналог группировки в SQL базах
данных
● выбираем данные по критерию и работаем с
ними:
– группируем дальше ( можно делать
многоступенчатую аггрегацию)
– меняем формат
– создаем новые поля на основании вычислений в
текущих (минимум, среднее, максимум и тд)
$geoNear
● Аналог near/nearSphere – но на этапе
аггрегации
● Требует наличия одного геоиндекса
● Не нужно указывать поле с координатами
● Может быть только первым этапом
аггрегирования
● Нельзя использовать одновременно с near*,
но можно geoWithin/Intersect
$geoNear пример – 6geonear.txt
db.test_collection1.aggregate([ {
$geoNear: {
near: { type: "Point", coordinates: [ 1 , 1.0000001 ] },
distanceField: "dist.calculated", # Название нового поля
для записи расстояния
maxDistance: 2, # Максимальное расстояние до точки
query: {name:"1"} , # ЗАпрос с дополнительной
фильтрацией
includeLocs: "dist.location", # Новое поле, где будут
дополнительно выведены координаты
spherical: true
}
} ])
GeoHaystack Index + geoSearch
● GeoHaystack ориентирован на:
– Запросы сначала по непространственному полю,
а затем по пространственному
– Данные из ограниченной области
● команда geoSearch - аналог geoNear для
коллекций с geoHaystack индексом
Пример использования GeoSearch
7geosearch.txt
> db.test_collection3.insert({ _id : 100, pos: { lng :
126.9, lat : 35.2 } , type : "restaurant"})
> db.test_collection3.insert({ _id : 200, pos: { lng :
127.5, lat : 36.1 } , type : "restaurant"})
> db.test_collection3.insert({ _id : 300, pos: { lng :
128.0, lat : 36.7 } , type : "national park"})
Пример использования GeoSearch
7geosearch.txt
db.test_collection3.createIndex( { pos :
"geoHaystack", type : 1 } ,{ bucketSize : 1 } )
db.runCommand( { geoSearch : "test_collection3" ,
search : { type: "restaurant" } ,
near : [-74, 40.74] ,
maxDistance : 1000 } )
Реальное использование в
Geo2Tag
● Geo2Tag – платформа для создания
геоконтекстных сервисов
● Геоданные – отдельные точки (широта,
долгота, высота) с привязанным
описанием/ссылкой
● REST интерфейс для поиска точек по
вхождению в пространственную область
● Индексирование через 2dSphere
● Запрос GeoWithin + запросы поиска по
высоте и параметрам описания
Что почитать
● Хороший туториал от создателей БД по
геовозможностям
https://docs.mongodb.org/manual/tutorial/geospat
ial-tutorial/
● Индексы, типы геометрий
https://docs.mongodb.org/manual/applications/g
eospatial-indexes/
● Введение в Mongo
http://jsman.ru/mongo-book/
● Формат GeoJSON http://geojson.org/

Работа с геоданными в MongoDb

  • 1.
    Работа с геоданнымив MongoDb Марк Заславский, mark.zaslavskiy@gmail.com
  • 2.
    О чем будетдоклад ● Обзор: – Короткое знакомство с Mongo – Коротко про GeoJson – Какие данные можно хранить в Mongo – Как хранить геоданные в Mongo – Как индексировать геоданные – Как выполнять запросы к данным (поиск объектов рядом/внутри/на пересечении с областями) ● Примеры использования геовозможностей MongoDb в Geo2Tag
  • 3.
    Примеры к докладу ●Ссылка для скачивания: http://bit.ly/1OHMY0N ● В архиве текстовые файлы со списками комманд для каждого примера ● Решетки (#) это не комментарий в Mongo, их нужно удалить ● Примеры проверялись на MongoDb 2.4.9
  • 4.
  • 5.
    Введение и мотивация ●Геоданные: – часто (но не всегда) = bigdata, – имеют сложные алгоритмы анализа/обработки, – могут иметь сложную структуру (границы областей, маршруты). ● Mongo – из коробки умеет работать с геоданными, – хорошо масштабируется, – представление геоданных стандартизовано (GeoJSON).
  • 6.
    Короткое введние вMongo ● MongoDb – документо- ориентированная СУБД ● Данные хранятся в BSON (почти JSON) ● Документы объединяются в коллекции ● У коллекций нет обязательной схемы ● MapReduce ● Полнотекстовый поиск
  • 7.
    Коллекции и документы ●Примерное соответствие с SQL СУБД: – Коллекция = таблица – Документ = запись в таблице – Идентификатор _id (обязательное поле документа) = первичный ключ ● Коллекции и базы данных создаются “ленивым образом”
  • 8.
    Пример CRUD 1mongo_crud.txt $mongo test_db > db.test_collection.insert({key1:'val1', key2:'val2'}) > db.test_collection.insert({key3:'val3'}) > db.test_collection.find({key3:'val3'}) > db.test_collection.find() > db.test_collection.remove({key3:'val3'}) > db.test_collection.find() > db.test_collection.update({ "key1" : "val1", "key2" : "val2" }, {$set: {"key1" : "val2"}})
  • 9.
    Формат GeoJSON ● НадмножествоJSON для хранения точек, ломаных и многоугольников (а также их совокупностей (гладких кривых нет:)). ● Не накладывает ограничение на тип координат (плоские, сферические, параболические ...). ● Координаты точки задаются в виде массива [x , y] Или [долгота, широта]
  • 10.
  • 11.
  • 12.
    GeoJSON - инструменты ●Генерация GeoJSON по карте - http://geojson.io/ ● Валидатор - http://geojsonlint.com/ ● Бьютификатор - https://jsonformatter.curiousconcept.c om/ ● Описание стандарта – http://geojson.org/
  • 13.
    Как сохранить геоданныев БД ● Форматы: – legacy coordinate pairs (только точки) [x,y] – GeoJson (точки, линии, полигоны ...) ● Нет контроля типов у полей координат ● Одно поле = один формат представления ● Можно сохранять как в отдельное поле, так и во вложенное
  • 14.
    Сохранение геоданных вБД – пример 2location_writing.txt $ mongo test_db > db.test_collection1.insert({ name: '1', location : { "type" : "Point", "coordinates" : [ 1.0, 1.0 ] } }) > db.test_collection2.insert({ name: '2', location : [ 1.0, 1.0 ] })
  • 15.
    Пространственные индексы - преамбула ●Индексы – ускорение запросов. ● Разные геометрии: – Плоская (евклидово расстояние) – Сферическая WGS84, http://spatialreference.org/ref/epsg/4326/) http://www.colorado.edu/geography/gcraft/notes/datum/gif/geoid2.gif
  • 16.
    Пространственные индексы ● 2dsphere –Сферическая геометрия, GeoJSON или legacy coordinate pairs – Можно делать связанный индекс с несколькими полями ● 2d – Плоская геометрия, legacy coordinate pairs – Связанный индекс только с одним полем ● geoHaystack – 2d + одно не геополе, быстрее на малых площадях чем 2d
  • 17.
    Пример - Создаеминдекс 3indexes_creation.txt > db.test_collection1.createIndex({ location: '2dsphere'}) > db.test_collection2.createIndex({ location: '2d'}) # Проверяем индексы > db.system.indexes.find()
  • 18.
    $geoWithin и $geoIntersects ●Что это: – Критерии для поиска (могут быть частью сложного запроса) – Поиск либо объектов внутри (geoWithin), либо на пересечении с областью (geoIntersects) – Работает для всех геометрий и типов задания координат ● Особенности – Индекс не нужен – Есть проблема с ооочень большими областями фильтрации
  • 19.
    $geoWithin и $geoIntersects ●Что приходит в ответ - список документов без сортировки ● Как можно искать: – Сферическая геометрия: $geometry, $centerSphere – Плоская геометрия: $box, $polygon, $center
  • 20.
    Пример про $geoWithin 4geowithin.txt db.test_collection1.find({ location : { $geoWithin : { $geometry : { type : "Polygon" , coordinates : [ [ [ 0 , 0 ] , [ 3 , 6 ] , [ 6 , 1 ] , [ 0 , 0 ] # Замыкаем фигуру ] ] } } } } )
  • 21.
    Пример про $geoWithin 4geowithin.txt db.test_collection1.find({ location : { $geoWithin : { $centerSphere: [ [1, 1], # Центр 2] # Радиус в радианах }}})
  • 22.
    Пример про $geoIntersects 4geointersects.txt db.test_collection1.find({ location : { $geoIntersects : {$geometry: {"type": "LineString", "coordinates": [ [0, 1], [1, 1] ] } } } })
  • 23.
    $near и $nearSphere ●Что это: операторы поиска объектов, близких к точке. ● Особенности – Near – использует евклидово расстояние, nearSphere – сферическое. – Требует наличия любого геоиндекса. – Нельзя комбинировать со сложными запросами, требующими специальный индекс – Можно задать пределы расстояний.
  • 24.
    $near и $nearSphere ●Что приходит в ответ: отсортированные по расстоянию документы ● Единицы измерения расстояний зависят от того, как задана точка отсчета: – GeoJSON – метры – Legacy pair - радианы
  • 25.
    Пример - поискточек по расстоянию 5nearsphere.txt db.test_collection1.find( { location : { $nearSphere: { $geometry : { type : "Point", coordinates : [ 0, 0 ]}, # Точка отсчета $maxDistance : 190000} # В метрах } })
  • 26.
    Операции аггрегирования ● примерныйаналог группировки в SQL базах данных ● выбираем данные по критерию и работаем с ними: – группируем дальше ( можно делать многоступенчатую аггрегацию) – меняем формат – создаем новые поля на основании вычислений в текущих (минимум, среднее, максимум и тд)
  • 27.
    $geoNear ● Аналог near/nearSphere– но на этапе аггрегации ● Требует наличия одного геоиндекса ● Не нужно указывать поле с координатами ● Может быть только первым этапом аггрегирования ● Нельзя использовать одновременно с near*, но можно geoWithin/Intersect
  • 28.
    $geoNear пример –6geonear.txt db.test_collection1.aggregate([ { $geoNear: { near: { type: "Point", coordinates: [ 1 , 1.0000001 ] }, distanceField: "dist.calculated", # Название нового поля для записи расстояния maxDistance: 2, # Максимальное расстояние до точки query: {name:"1"} , # ЗАпрос с дополнительной фильтрацией includeLocs: "dist.location", # Новое поле, где будут дополнительно выведены координаты spherical: true } } ])
  • 29.
    GeoHaystack Index +geoSearch ● GeoHaystack ориентирован на: – Запросы сначала по непространственному полю, а затем по пространственному – Данные из ограниченной области ● команда geoSearch - аналог geoNear для коллекций с geoHaystack индексом
  • 30.
    Пример использования GeoSearch 7geosearch.txt >db.test_collection3.insert({ _id : 100, pos: { lng : 126.9, lat : 35.2 } , type : "restaurant"}) > db.test_collection3.insert({ _id : 200, pos: { lng : 127.5, lat : 36.1 } , type : "restaurant"}) > db.test_collection3.insert({ _id : 300, pos: { lng : 128.0, lat : 36.7 } , type : "national park"})
  • 31.
    Пример использования GeoSearch 7geosearch.txt db.test_collection3.createIndex({ pos : "geoHaystack", type : 1 } ,{ bucketSize : 1 } ) db.runCommand( { geoSearch : "test_collection3" , search : { type: "restaurant" } , near : [-74, 40.74] , maxDistance : 1000 } )
  • 32.
    Реальное использование в Geo2Tag ●Geo2Tag – платформа для создания геоконтекстных сервисов ● Геоданные – отдельные точки (широта, долгота, высота) с привязанным описанием/ссылкой ● REST интерфейс для поиска точек по вхождению в пространственную область ● Индексирование через 2dSphere ● Запрос GeoWithin + запросы поиска по высоте и параметрам описания
  • 33.
    Что почитать ● Хорошийтуториал от создателей БД по геовозможностям https://docs.mongodb.org/manual/tutorial/geospat ial-tutorial/ ● Индексы, типы геометрий https://docs.mongodb.org/manual/applications/g eospatial-indexes/ ● Введение в Mongo http://jsman.ru/mongo-book/ ● Формат GeoJSON http://geojson.org/