Представьте себе базу данных, способную валидировать 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 библиотека для использования в своих проектах
- Документация
Автор: andrey665