Концептуальные проблемы с IndexedDB (отношения и т.д.)

Я пишу дипломную работу об автономных возможностях веб-приложений. Моя задача - показать возможности автономного хранения данных через веб-приложение с реляционной базой данных на стороне сервера и Ajax/JSON трафиком между клиентом и сервером. Моя первая реализация использовала подход с localStorage, сохраняя каждый Ajax-ответ как значение с URL запроса в качестве ключа. Приложение работает просто отлично. Однако на следующем этапе я хочу (т.е. этого требует диссертация) реализовать более продвинутую версию с базой данных на стороне клиента. Поскольку на сервере поддерживается реляционная база данных, интуитивно понятным выбором была бы Web SQL Database. Но, как мы знаем, этот стандарт устарел, и я не хочу использовать технологию, будущее которой неопределенно. Таким образом, я хочу использовать IndexedDB для реализации логики базы данных на стороне клиента. К сожалению, после прочтения множества материалов в Интернете, которые в основном лишь слегка царапают поверхность (приложения todo-notes и т.д.), я все еще не знаю, как действовать дальше.

Моя задача кажется довольно простой: реализовать серверную базу данных на клиенте с помощью 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": { /* 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, все работает нормально и нет никаких шансов на нестыковки.

31
задан Cœur 3 September 2017 в 13:31
поделиться