Я пишу диссертацию об автономных способностях веб-приложений. Моя задача - показать возможности автономного хранения через веб-приложение с серверной реляционной базой данных и Ajax/JSON-трафиком между клиентом и сервером. Моя первая реализация использовала подход с localStorage, сохраняя каждый ответ Ajax как значение с URL-адресом запроса в качестве ключа. Приложение работает отлично. На следующем шаге, однако, я хочу (то есть, тезис требует) реализовать более продвинутую версию с клиентской базой данных. Поскольку сервер поддерживает реляционную базу данных, Web SQL Database была бы интуитивным выбором. Но, как мы знаем, стандарт устарел, и я не хочу использовать технологию, будущее которой неопределенно. Таким образом, я хочу использовать IndexedDB для реализации логики базы данных на стороне клиента. К сожалению, после прочтения большого количества материалов в Интернете, которые в основном хранят очень много царапин на поверхности (todo-notes applications и т.д.), Я до сих пор не знаю, как действовать.
Моя задача выглядит довольно простой: реализовать серверную базу данных на клиенте с помощью IndexedDB для репликации всех данных, которые были однажды получены с сервера. Проблемы, которые делают это намного менее прямолинейными:
- База данных на стороне сервера является реляционной, IndexedDB является (более или менее) объектно-ориентированной
- Нет интуитивного способа синхронизации баз данных на стороне клиента и на сервере
- Нет интуитивного способа реализации отношений в IndexedDB, которые реализованы с использованием внешних ключей и JOIN на сервере
Сейчас у меня есть концепция, которую я действительно боюсь начать реализовывать. Я подумал о создании хранилища объектов для каждой таблицы в базе данных сервера и запрограммировать объекты отношений в разных хранилищах объектов вручную. В моем приложении, которое, короче говоря, управляет курсами университета, у меня будет 7 объектов магазинов.
Я хочу продемонстрировать свою идею с примером для ответа JSON с сервера (/* это комментарии */):
{ "course": { /* course object */
"id":1,
"lecturer": { "id":"1", /* lecturer object with many attributes */ },
"semester": { "id":"1", /* semester object with many attributes */ },
/* more references and attributes */
}}
Алгоритм хранения данных с помощью IndexedDB сохранит каждый объект, который применяется к хранилищу объектов в соответствующем хранилище объектов, и заменит объекты ссылками на эти объекты. Например, вышеуказанный объект курса будет выглядеть следующим образом в хранилище объектов "курс":
{ "course": { /* course object */
"id":1,
"lecturer":
{ "reference": { /* reference to the lecturer in the object store 'lecturer' */
"objectstore":"lecturer",
"id":"1" }
},
"semester":
{ "reference": { /* reference to the semester in the object store 'semester' */
"objectstore":"semester",
"id":"1" }
}
/* more references and attributes */
}}
Алгоритм извлечения данных с помощью IndexedDB будет делать следующее (у меня есть рекурсивный шаблон смутно):
Retrieve the course object with id=1 from the object store 'course'
For each reference object in the retrieved course object, do
Retrieve the object with id=reference.id from the object store reference.objectstore
Replace the reference object with the retrieved object
Ясно видно, что эта реализация была бы очень громоздкой, особенно из-за асинхронного характера IndexedDB. Это также привело бы к множеству различных транзакций в базе данных, чтобы получить объект курса, и производительность сильно пострадает (я действительно не знаю, как выглядит производительность транзакций IndexedDB).
Как я могу сделать это лучше и проще?
Я уже посмотрел на эти потоки, которые представляют схожие проблемы: link1, link2. Я не вижу в них более простых решений. Более того, я бы предпочел избежать использования инфраструктуры обертки IndexedDB из-за нескольких причин.
Я мог бы также предположить, что я полностью ошибаюсь с IndexedDB для моей проблемы.
Edit:
Наконец я закончил свой подход, чтобы хранить ссылки в самих объектах в IndexedDB. Это может привести к некоторым проблемам с производительностью в случае больших объемов данных со многими ссылками. Однако, если их использовать разумно, в большинстве случаев можно избежать огромных количеств итераций и удалений базы данных, и нет необходимости хранить сложную схему базы данных в памяти или в самой IndexedDB.
Как правило, я должен сказать, что у меня создается впечатление, что я неправильно интерпретирую динамическую и прямую идею с IndexedDB как базу данных схемы. Но что бы то ни было, я реализовал все на JavaScript, он отлично работает и нет никаких шансов на какие-либо несоответствия.