В наше время скорость работы WEB-приложения сильно влияет на лояльность пользователей. Зачастую приходится переносить некоторую бизнес-логику в клиентский код, работающий в браузере пользователя.
В такой ситуации появляется необходимость оперативного получения данных, связанных с задачами. Но иногда время на их запрос с серверной базы данных слишком велико, а порой подключение к сети и вовсе нестабильно или отсутствует. В такой ситуации можно прибегнуть к хранению данных локально у пользователя и синхронизировать по мере необходимости.
PouchDB — база данных, которая работает на основе существующих решений по хранению информации в браузере пользователя. По сути, она выступает фасадом и обеспечивает универсальный API независимо от того, в каких условиях запущено приложение.
Версии браузеров, в которых работает PouchDB:
Так как это NoSQL база данных, терминология немного отличается от привычных реляционных решений. Посмотреть разницу можно в таблице соответствия:
Для создания БД достаточно выполнить:
и с ней уже можно работать. Создавать, удалять и читать данные из PouchDB так же просто:
Одним из основных направлений применения такого функционала является непрерывная работа с точки зрения пользователя. Например, пользователь начал заполнять форму какими-нибудь данными, до тех пор пока он не закончил, можно сохранять их локально. Таким образом, можно не только дать возможность пользователю прерваться, но и защититься от потери введенных данных в случае ошибок во время отправки их на сервер.
Локальные базы данных также могут быть использованы для кэширования. Например, пользователь со своего смартфона просматривает объявления. Можно локально сохранить список и предоставлять информацию значительно быстрее.
Другим направлением является работа оффлайн. К примеру, пользователь может управлять своими заметками без доступа в интернет, при этом они синхронизируются, как только появится доступ. Да и вообще, можно строить полноценные офлайн или десктопные приложения, никак не ограничивая функциональность и без дополнительных затрат на поддержку или аренду серверов.
Главной особенностью PouchDB является гибкая система синхронизации. Эта база данных может синхронизироваться с другими локальными и удаленными системами. Такой функционал доступен из коробки и не требует дополнительных настроек или написания большого количества кода.
Единственным условием является то, что синхронизироваться можно только с CouchDB-like протоколами. Это может быть CouchDB, Cloudant, Couchbase Sync Gateway или PouchDB Server. Последний, в свою очередь, может быть прослойкой между другими сервисами, как Redis, Riak или MySQL, через LevelUP экосистему.
Пример простой синхронизации:
Во время синхронизации может возникнуть конфликтная ситуация, когда на обеих сторонах запись была изменена с момента последней актуализации. В PouchDB для правильного разрешения таких конфликтов используется система ревизий записей.
У каждой сущности имеется своя история изменений. Каждое изменение, в том числе «создание», генерирует уникальный идентификатор версии сущности:
При любых операциях с сущностями необходимо указывать номер ревизии. В простейших случаях это помогает решить так называемые «непосредственные конфликты», используя оптимистическую блокировку.
В реальной жизни есть более серьезная проблема — «возможные конфликты». Они могут возникать во время синхронизации баз данных, и тогда понять какая из версий записи должна остаться в конечном итоге становится не так просто. В PouchDB для решения таких ситуаций ведется запись истории изменений сущности, и сохраняются все версии во время синхронизации.
Это позволяет разрешить конфликт без блокировки процесса синхронизации, как с помощью алгоритма, так и вручную.
Варианты синхронизации могут быть разные: однонаправленная репликация в любую из двух сторон, двунаправленная репликация.
Настройка происходит с помощью нескольких строк кода:
или в другую сторону:
или сразу в обе:
Как и ожидается, можно обрабатывать события генерируемые во время синхронизации:
Использовать такую функциональность можно для разных типов приложений:
Для упрощения и ускорения поиска по содержимому в PouchDB используются Map/Reduce-функции. Близкой аналогией к ним является построение индекса в реляционной базе данных.
Например для «индексирования» поля name в документе можно использовать такую конструкцию:
Использование созданной функции выглядит следующим образом:
Можно использовать большое количество различных параметров влияющих на выборку, например, максимальное количество записей, вывод полной информации о документе или только его идентификатора и другие:
Сначала нужно создать map-функцию, например:
Она будет «индексировать» указанные поля. При этом можно управлять обработкой каждого значения. В примере ниже обрабатываются только документы с типом brick, и только поле color. К тому же, синий цвет будет обработан и сохранен как строка «Wow! Blue brick!».
Далее по созданным индексам можно выполнять поиск или агрегировать данные по какому-либо параметру. Для этого используются reduce-функции, они объединяют все данные, полученные после работы map-функции и обрабатывают их нужным образом. Используя написанную map-функцию можно реализовать:
Таким образом, сначала мы будем отбирать записи по указанным параметрам и в конечном итоге посчитаем количество найденных документов:
На этом функциональность PouchDB не ограничивается.
Существует еще много функций, рекомендованных к использованию продвинутым пользователям. А если возможностей «из коробки» недостаточно, можно подключить один или несколько плагинов. Их выбор достаточно велик и постоянно расширяется.
Сталкиваясь с проблемами быстрого доступа к данным, организации serverless-архитектуры и нестабильного интернет-соединения, можно обратить внимание на PouchDB, как на один из вариантов их решения.
В такой ситуации появляется необходимость оперативного получения данных, связанных с задачами. Но иногда время на их запрос с серверной базы данных слишком велико, а порой подключение к сети и вовсе нестабильно или отсутствует. В такой ситуации можно прибегнуть к хранению данных локально у пользователя и синхронизировать по мере необходимости.
Знакомство
PouchDB — база данных, которая работает на основе существующих решений по хранению информации в браузере пользователя. По сути, она выступает фасадом и обеспечивает универсальный API независимо от того, в каких условиях запущено приложение.
Версии браузеров, в которых работает PouchDB:
- Firefox 29+ (включая Firefox OS и Firefox для Android)
- Chrome 30+
- Safari 5+
- Internet Explorer 10+
- Opera 21+
- Android 4.0+
- iOS 7.1+
- Windows Phone 8+
Так как это NoSQL база данных, терминология немного отличается от привычных реляционных решений. Посмотреть разницу можно в таблице соответствия:
Базовый API
Для создания БД достаточно выполнить:
и с ней уже можно работать. Создавать, удалять и читать данные из PouchDB так же просто:
Где использовать?
Одним из основных направлений применения такого функционала является непрерывная работа с точки зрения пользователя. Например, пользователь начал заполнять форму какими-нибудь данными, до тех пор пока он не закончил, можно сохранять их локально. Таким образом, можно не только дать возможность пользователю прерваться, но и защититься от потери введенных данных в случае ошибок во время отправки их на сервер.
Локальные базы данных также могут быть использованы для кэширования. Например, пользователь со своего смартфона просматривает объявления. Можно локально сохранить список и предоставлять информацию значительно быстрее.
Другим направлением является работа оффлайн. К примеру, пользователь может управлять своими заметками без доступа в интернет, при этом они синхронизируются, как только появится доступ. Да и вообще, можно строить полноценные офлайн или десктопные приложения, никак не ограничивая функциональность и без дополнительных затрат на поддержку или аренду серверов.
Репликация и конфликты
Главной особенностью PouchDB является гибкая система синхронизации. Эта база данных может синхронизироваться с другими локальными и удаленными системами. Такой функционал доступен из коробки и не требует дополнительных настроек или написания большого количества кода.
Единственным условием является то, что синхронизироваться можно только с CouchDB-like протоколами. Это может быть CouchDB, Cloudant, Couchbase Sync Gateway или PouchDB Server. Последний, в свою очередь, может быть прослойкой между другими сервисами, как Redis, Riak или MySQL, через LevelUP экосистему.
Во время синхронизации может возникнуть конфликтная ситуация, когда на обеих сторонах запись была изменена с момента последней актуализации. В PouchDB для правильного разрешения таких конфликтов используется система ревизий записей.
У каждой сущности имеется своя история изменений. Каждое изменение, в том числе «создание», генерирует уникальный идентификатор версии сущности:
При любых операциях с сущностями необходимо указывать номер ревизии. В простейших случаях это помогает решить так называемые «непосредственные конфликты», используя оптимистическую блокировку.
В реальной жизни есть более серьезная проблема — «возможные конфликты». Они могут возникать во время синхронизации баз данных, и тогда понять какая из версий записи должна остаться в конечном итоге становится не так просто. В PouchDB для решения таких ситуаций ведется запись истории изменений сущности, и сохраняются все версии во время синхронизации.
Это позволяет разрешить конфликт без блокировки процесса синхронизации, как с помощью алгоритма, так и вручную.
Настройка происходит с помощью нескольких строк кода:
или в другую сторону:
или сразу в обе:
Как и ожидается, можно обрабатывать события генерируемые во время синхронизации:
Использовать такую функциональность можно для разных типов приложений:
- In-memory ? Local (для кеширования данных);
- Local ? Local (между браузерами или приложениями без серверной части);
- Remote ? Remote (репликация);
- Local ? Remote ? Local (синхронизация с бэкапированием на сервере).
Map/Reduce функции
Для упрощения и ускорения поиска по содержимому в PouchDB используются Map/Reduce-функции. Близкой аналогией к ним является построение индекса в реляционной базе данных.
Например для «индексирования» поля name в документе можно использовать такую конструкцию:
Использование созданной функции выглядит следующим образом:
Можно использовать большое количество различных параметров влияющих на выборку, например, максимальное количество записей, вывод полной информации о документе или только его идентификатора и другие:
Сначала нужно создать map-функцию, например:
Далее по созданным индексам можно выполнять поиск или агрегировать данные по какому-либо параметру. Для этого используются reduce-функции, они объединяют все данные, полученные после работы map-функции и обрабатывают их нужным образом. Используя написанную map-функцию можно реализовать:
Таким образом, сначала мы будем отбирать записи по указанным параметрам и в конечном итоге посчитаем количество найденных документов:
Заключение
На этом функциональность PouchDB не ограничивается.
Существует еще много функций, рекомендованных к использованию продвинутым пользователям. А если возможностей «из коробки» недостаточно, можно подключить один или несколько плагинов. Их выбор достаточно велик и постоянно расширяется.
Сталкиваясь с проблемами быстрого доступа к данным, организации serverless-архитектуры и нестабильного интернет-соединения, можно обратить внимание на PouchDB, как на один из вариантов их решения.
Комментарии (4)
RouR
14.11.2017 17:20Ограничение на размер БД? 50Мб? На всех платформах?
Reksoftman Автор
15.11.2017 08:39RouR, вот здесь можно почитать подробнее: pouchdb.com/faq.html#data_limits
Ashot
Только синхронизируется не со всем подряд – это должна быть БД с CouchDB-like протоколом. https://pouchdb.com/faq.html – первые 2 пункта из faq про это. Неплохо было бы отметить это в статье.
На сколько я понял, заставить PouchDB синхронизироваться с чем-то отличным от CouchDB можно через pouchdb-server (в этом могу ошибаться, очень поверхностно этот вопрос рассмотрел)
Reksoftman Автор
Ashot, спасибо за ваш комментарий! Мы добавили в статью уточнение.