Я пишу дипломную работу об автономных возможностях веб-приложений. Моя задача - показать возможности автономного хранения данных через веб-приложение с реляционной базой данных на стороне сервера и Ajax/JSON трафиком между клиентом и сервером. Моя первая реализация использовала подход с localStorage, сохраняя каждый Ajax-ответ как значение с URL запроса в качестве ключа. Приложение работает просто отлично. Однако на следующем этапе я хочу (т.е. этого требует диссертация) реализовать более продвинутую версию с базой данных на стороне клиента. Поскольку на сервере поддерживается реляционная база данных, интуитивно понятным выбором была бы Web SQL Database. Но, как мы знаем, этот стандарт устарел, и я не хочу использовать технологию, будущее которой неопределенно. Таким образом, я хочу использовать IndexedDB для реализации логики базы данных на стороне клиента. К сожалению, после прочтения множества материалов в Интернете, которые в основном лишь слегка царапают поверхность (приложения todo-notes и т.д.), я все еще не знаю, как действовать дальше.
Моя задача кажется довольно простой: реализовать серверную базу данных на клиенте с помощью IndexedDB для репликации всех данных, которые когда-то были получены с сервера. Проблемы, которые делают эту задачу не такой простой:
Сейчас у меня в голове есть концепция, которую я очень боюсь начинать реализовывать. Я думал о том, чтобы создать объектное хранилище для каждой таблицы в серверной базе данных и запрограммировать объекты отношений в разных объектных хранилищах вручную. В моем приложении, которое, вкратце, управляет курсами университета, у меня будет 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": { /* 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, все работает нормально и нет никаких шансов на нестыковки.