В этом году я продемонстрировал, как легко создавать современные веб-приложения, используя AngularJS, Java и MongoDB . Я также использую Groovy во время этой демонстрации, чтобы делать то, что Groovy действительно хорошо умеет писать описательные тесты и создавать сценарии.
Из-за нехватки времени в демоверсии у меня никогда не было возможности углубиться в детали сценария, который я использую, поэтому цель этого давно ожидаемого поста в блоге состоит в том, чтобы немного подробнее рассмотреть этот сценарий Groovy.
Во-первых, я хочу уточнить, что это не моя оригинальная работа — я
большинство идей для демонстрации у моего коллеги Росса Лоули. В этом посте он подробно рассказывает о том, как он создал приложение, которое находит самые популярные названия пабов в Великобритании. Там есть раздел, где он рассказывает о загрузке открытых карт улиц и использовании python для преобразования XML во что-то более удобное для MongoDB — именно этот процесс я в основном украл, переработал для кафе и переписал для JVM.
украл
Я предполагаю, что если вы работали с Java в течение какого-то периода времени, наступил момент, когда вам нужно было использовать его для анализа XML. Поскольку предполагается, что моя демонстрация посвящена тому, как легко работать с Java, я не хотел этого делать. Когда я писал демо, я не очень хорошо знал Groovy, но я знал, что он встроил поддержку синтаксического анализа и манипулирования XML, что я и хотел делать. Кроме того, создавать Карты (структуры данных, а не географические) с помощью Groovy очень просто, и это действительно то, что нам нужно вставить в MongoDB .
Цель сценария
- Разобрать файл XML, содержащий открытые данные карт улиц всех кофеен.
- Извлеките атрибуты XML широты и долготы и преобразуйте их в MongoDB GeoJSON .
- Выполните некоторую базовую проверку данных кафе из XML.
- Вставьте в MongoDB.
- Убедитесь, что MongoDB знает, что он содержит данные геолокации с возможностью запроса.
Сценарий PopulateDatabase.groovy , по этой ссылке вы перейдете к версии, которую я представил на JavaOne:
Во-первых, нам нужны данные
Я использовал тот же сервис, который Росс использовал в своем блоге, чтобы получить XML-файл, содержащий «все» кафе по всему миру. Теперь, открытые данные карт улиц несколько… необработанные и неструктурированные (вот почему MongoDB является таким прекрасным инструментом для их хранения), поэтому я не уверен, что у меня действительно есть все кафе, но я получил достаточно данных для интересного демонстрация с использованием
http://www.overpass-api.de/api/xapi?*[amenity=cafe][cuisine=coffee_shop]
Полученный файл XML в проекте GitHub, но если вы попробуете это сами вы могли бы (на самом деле, вероятно , будет) получить разные результаты.
Каждая запись XML выглядит примерно так:
<node id="178821166" lat="40.4167226" lon="-3.7069112">
<tag k="amenity" v="cafe"/>
<tag k="cuisine" v="coffee_shop"/>
<tag k="name" v="Chocolatería San Ginés"/>
<tag k="wheelchair" v="limited"/>
<tag k="wikipedia" v="es:Chocolatería San Ginés"/>
</node>
Каждое кафе имеет уникальный идентификатор, а также широту и долготу в качестве атрибутов node элемента. Внутри этого узла есть ряд tag элементов, все с k и v атрибутами. Каждый кафе имеет различное количество этих атрибутов, и они не совместимы от магазина к магазину (кроме amenity и cuisine которые мы использовали , чтобы выбрать эти данные).
Инициализация
Прежде чем делать что-то еще, мы хотим подготовить базу данных. Предположение этого сценария состоит в том, что либо коллекция, в которой мы хотим хранить кофейни, пуста, либо полна устаревших данных. Поэтому мы собираемся использовать Java-драйвер MongoDB, чтобы получить интересующую нас коллекцию, а затем отбросить ее.
Здесь есть две интересные вещи:
- Этот скрипт Groovy просто использует базовый драйвер Java. Groovy может очень счастливо общаться с ванильной Java, ей не нужно использовать библиотеку Groovy. Существуют специфичные для Groovy библиотеки для общения с MongoDB (например, плагин MongoDB GORM ), но драйвер Java работает на отлично.
- Вам не нужно создавать базы данных или коллекции (коллекции немного похожи на таблицы, но менее структурированы) явно в MongoDB. Вы просто используете интересующую вас базу данных и коллекцию, и, если она еще не существует, сервер создаст их для вас.
В этом примере мы просто используем конструктор по умолчанию для MongoClientкласса, представляющего соединение с серверами баз данных. По умолчанию это localhost: 27017, где я и работаю с базой данных. Однако вы можете указать свой собственный адрес и порт — для получения более подробной информации см. Начало работы с MongoDB и Java .
Превратите XML в нечто в форме MongoDB
Итак, далее мы собираемся использовать XmlSlurper Groovy для чтения XML-данных открытой карты улиц, о которых мы говорили ранее. Для того, чтобы перебирать каждый узел мы используем: xmlSlurper.node.each. Для тех из вас, кто является новичком в Groovy или новичком в Java 8, вы можете заметить, что он использует замыкание для определения поведения, применяемого к каждому элементу «узла» в XML.
Создать GeoJSON

coffeeShop которая содержит структуру документа, представляющую кафе, которое мы хотим сохранить в базе данных. Во-первых, мы инициализируем эту карту с атрибутами node. Помните, что эти атрибуты похожи на:
<node id="18464077" lat="-33.8911183" lon="151.1958773">
Мы собираемся сохранить идентификатор как значение для нового поля с именем openStreetMapId. Нам нужно сделать что-то более сложное с широтой и долготой, поскольку нам нужно сохранить их как GeoJSON, который выглядит примерно так:
{ 'location' : { 'coordinates': [<longitude>, <latitude>],
'type' : 'Point' } }
В строках 12-14 вы можете видеть , что мы создаем , Map что выглядит как GeoJSON, натягивая lat и lon атрибуты в соответствующих местах.
Вставить оставшиеся поля

tag элемента в XML мы получаем k атрибут и проверяем, является ли оно допустимым именем поля для MongoDB (оно не позволяет вставлять поля с точкой в, и мы не хотим переопределять наше тщательно сконструированное locationполе). Если это так, мы просто добавляем этот ключ в качестве поля и его соответствующий vатрибут в качестве значения на карту. Это эффективно копирует данные ключ / значение OpenStreetMap в пары ключ / значение в документе MongoDB, поэтому мы не теряем никаких данных, но также не делаем ничего особенно интересного для их преобразования.
Сохранить в MongoDB

coffeeShop карту, представляющую документ, который мы хотим сохранить в MongoDB, мы вставляем его в MongoDB, если на карте есть поле с именем name. Мы могли бы проверили это , когда мы читали XML и положить его в карту, но это на самом деле гораздо проще просто использовать довольно синтаксис Groovy для проверки ключа называется nameв coffeeShop.
Когда мы хотим вставить карту, нам нужно превратить это в BasicDBObjectтип документа драйвера Java, но это легко сделать, вызвав конструктор, который принимает карту. В качестве альтернативы, есть синтаксис Groovy, который фактически делает то же самое, что вы можете предпочесть:
collection.insert(coffeeShop as BasicDBObject)
Скажите MongoDB, что мы хотим выполнить гео-запросы на этих данных

locationполе как GeoJSON, поэтому все, что нам нужно сделать, это вызвать createIndex это поле.
Вывод
Итак, это все! Groovy — хороший инструмент для такого рода сценариев — он не только является языком сценариев, но и встроенной поддержкой XML, действительно красивым синтаксисом Map и поддержкой замыканий делает его идеальным инструментом для итерации по данным XML и превращая его во что-то, что можно вставить в коллекцию MongoDB.



