Представьте себе базу данных, способную валидировать JSON данные по схеме JSON Schema, отрабатывать события и обрабатывать данные. А если идея реализованна как сервис, использующий mongodb?
Мы разработали именно такой сервис. Им пользуются наши сайд проекты:
- docast.me — любые источники данных можно слушать/смотреть в любимом подкастинговом приложении
- watchlater — решение проблемы watch later youtube
- warhealth — мобильное приложение
Под катом краткое описание основных особенностей сервиса с примерами.
Эта статья содержит разделы:
- JSON — JSON документы
- Validation — валидация данных
- Files — работа с файлами
- Processing — процессинг данных
- WebHook — отработка событий
JSON
Все сущности в сервисе являются JSON документами. Благодаря этому нам отлично подошла mongodb.
Вы можете работать с документами через HTTP REST Api, CLI и Python клиенты.
Я предпочитаю CLI.
Вот несколько примеров его использования:
- Создать документ в коллекции
venues
deform document create -c venues -d '{"text":"hello world"}'
- Узнать сколько пользователей в проекте
$ deform documents count -c my_project_users 108
Validation
Скажу сразу — выбор пал на JSON Schema draft v4. Эта схема предоставляет много полезного.
Допустим, что к вам приходит 2 документа:
{ "name": "Товар за 1 руб", "price": 1.0, "currency": "RUB" }
{ "name": "1$ stuff", "price": 1.99, "currency": "United States Dollar" }
И нам нужно, чтобы второй документ не прошел в базу — у него же неправильно передали валюту ( свойство currency ).
Давайте создадим схему, по которой первый документ пройдет, а второй — нет.
{ "description": "General goods schema", "type": "object", "properties": { "name": { "type": "string" }, "price": { "type": "number" }, "currency": { "type": "string", "enum": ["RUB", "USD", "CAD", "GBP"] } }, "required": ["name", "price", "currency"] }
Обратите внимание на currency и его свойство enum. Лишь документы, у которых валюта совпадает со строками "RUB", "USD", "CAD", "GBP" будут считаться корректными.
Files
Deform поддерживает работу с файлами. Все ваши вайлы будут являться документами в коллекции _files. А в самом документе, куда вы прикрепили файл он также будет доступен в виде объекта.
Давайте добавим в схему с товарами новое свойство — изображение товара.
{ "description": "General goods schema", "type": "object", "properties": { "name": { "type": "string" }, "price": { "type": "number" }, "currency": { "type": "string", "enum": ["RUB", "USD", "CAD", "GBP"] }, "image": { "type": "file" } }, "required": ["name", "price", "currency"] }
Теперь мы можем загрузить картинку к этому товару.
Используя CLI, создадим документ:
$ deform document create -c goods -d '{ "name": "Teapot", "price": 11.99, "currency": "GBP", "image": @"/tmp/teapot.png" }'
В результате получим
{ "_id": "576ffce308888f000599ee17", "name": "Teapot", "price": 11.99, "currency": "GBP", "image": { "_id": "5772db5308888f000599f095", "collection_id": "goods", "content_type": "image/png", "date_created": "2016-06-25T18:31:12.356Z", "document_id": "576ec022bd4db46b765ae94a", "last_access": "2016-06-25T17:32:18.347Z", "md5": "a8eda376612338e0286ff1c1a725b111", "name": "teapot.png", "size": 16214 } }
Получить содержимое файла можно как из коллекции с файлами и из самого документа товара.
Ссылка на раздел документации с файлами
Processing
Deform может обрабатывать данные. Полный список обработчиков.
Допустим, что нам надо изменить размер изображения товара в момент его создания.
В этом нам поможет процессор resize ( на данный момент он работает с только изображениями )
Схема превратится в:
{ "description": "General goods schema", "type": "object", "properties": { "name": { "type": "string" }, "price": { "type": "number" }, "currency": { "type": "string", "enum": ["RUB", "USD", "CAD", "GBP"] }, "photo": { "type": "file" }, "300x150": { "type": "file", "processors": [ { "name": "resize", "in": { "original_image": { "property": "photo" }, "size": { "value": [300,150] } } } ] } } }
Ссылка на раздел документации с процессингом
Webhook
Наши вэбхуки пишут историю и у них есть события. Еще у них есть заголовки, методы и своя валидация совпавших документов.
Допустим, что нам нужна нотификация в slack о том, что товар был создан. Хук будет выглядеть так:
{ "name": "Slack notification", "url": "https://hooks.slack.com/services/....", "method": "POST", "triggers": ["created"], "collection": "slack_notifications" }
Обратите внимание на свойство triggers — в данном случае лишь созданные документы будут вызывать срабатывание хука.
А теперь допустим, что нам нужны уведомления только о товарах, где цена больше 1000 и валюта USD:
{ "name": "Slack notification", "url": "https://hooks.slack.com/services/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", "method": "POST", "triggers": ["created"], "collection": "slack_notifications", "condition": { "type": "object", "additionalProperties": true, "price": { "type": "number", "minimum": 999 }, "currency": { "type": "string", "enum": ["USD"] } } }
Если документ будет корректен для схемы внутри condition — хук будет отрабатывать.
Ссылка на раздел документации с хуками
Заключение
Эта статья является небольшим обзором основных возможностей проекта.
Если вам он интересен — буду раз любой обратной связи, включая объективную критику :D
Несколько ссылок по проекту:
- CLI — CLI для сервиса
- Python — Python библиотека для использования в своих проектах
- Документация
