最近趣味でIndexedDBを利用したオフライン完結型のアプリケーションを書いている。
他サイトのIndexedDBの利用例でMicrosoft To-Doで一番ちゃんと使われてた気がするので利用例としてスキーマを読み解く。
IndexedDBの確認方法
以前から使われているLocalStorageと比べて
- (ブラウザに依るが)単純に容量がでかい
- indexを貼れる
- Objectをそのまま格納出来る
あたりがメリットになる。
このあたりは別の記事を見るとよい
Chromeで中身を確認するには、DeveloperToolsのApplicationタブ、StorageのIndexedDBを見ればよい。
各テーブルのデータを確認出来る。

Microsoft To-Do
Microsoftが開発しているToDo管理アプリケーション。
タスクを複数格納出来るlistがある一般的なTodo管理アプリケーションで、オフラインで動作する。

Table
2018/4/6現在は以下の6テーブル
- settings
- steps
- tasks
- members
- lists
- sync
基本的にすべてのテーブルは1つのユニークキーを持っていて、キーに対してObjectを持っている様子。
settings
{
id: "l-5oo86"
key: "onboarding_detail_tooltip_dismissed"
local_id:"l-5oo86"
remote_id: undefined
value: true
}
- いわゆるkey,valueな感じのオブジェクトが保存されている。primaryKeyはkeyが設定されている。
- remote_idはtasksを見る限りサーバーサイドで持っているidが振られる様子だが、settingsに関してはremote_idが振られているレコードはないのでクライアントでのみ保存している可能性が高い
tasks
{
ChangeKey: "XAI/lv8jBkOPt79WuS0NSwAAnP2j=="
committed_day: undefined
completed: false
completed_at: undefined
created_at: {date_time: "2017-05-04T18:22:51.500", time_zone: "UTC"}
due_date: undefined
id: "AQMkADAwATM0MDAAMS1hZGNiLTQzYjYtMDACLTAwCgBGAAADVFc0lFz6P0m-xARjTHHhrAcAXAI-lv8jBkOPt79WuS0NSwAAAJzsHc4AAABcAj_W-yMGQ4_3v1a5LQ1LAAAAnOwloAAAA=="
is_ignored: undefined
is_reminder_on: false
list_id: "AQMkADAwATM0MDAAMS1hZGNiLTQzYjYtMDACLTAwCgAuAAADVFc0lFz6P0m-xARjTHHhrAEAXAI-lv8jBkOPt79WuS0NSwAAAJzsHc4AAA="
local_id: "AQMkADAwATM0MDAAMS1hZGNiLTQzYjYtMDACLTAwCgBGAAADVFc0lFz6P0m-xARjTHHhrAcAXAI-lv8jBkOPt79WuS0NSwAAAJzsHc4AAABcAj_W-yMGQ4_3v1a5LQ1LAAAAnOwloAAAA=="
note: ""
note_updated_at: undefined
position: 1493922090000
postponed_day: undefined
recurrence: undefined
reminder: undefined
remote_id: "AQMkADAwATM0MDAAMS1hZGNiLTQzYjYtMDACLTAwCgBGAAADVFc0lFz6P0m-xARjTHHhrAcAXAI-lv8jBkOPt79WuS0NSwAAAJzsHc4AAABcAj_W-yMGQ4_3v1a5LQ1LAAAAnOwloAAAA=="
remote_list_id: "AQMkADAwATM0MDAAMS1hZGNiLTQzYjYtMDACLTAwCgAuAAADVFc0lFz6P0m-xARjTHHhrAEAXAI-lv8jBkOPt79WuS0NSwAAAJzsHc4AAA="
source: undefined
title: "タスクネーム"
today_position: undefined
}
- primaryKeyはidになっている。
- remote_id, remote_list_idがおそらくサーバー側でのpkey。
- list_idはlistsのレコードに対する外部キー
- ChangeKeyを見てサーバーサイドのデータと動機を取っているように見える。
lists
{
background: "mountains"
id: "inbox"
is_owner: true
is_shared_folder: false
local_id: "inbox"
members: []
position: 1493835505000
remote_id: "AQMkADAwATM0MDAAMS1hZGNiLTQzYjYtMDACLTAwCgAuAAADVFc0lFz6P0m-xARjTHHhrAEAXAI-lv8jBkOPt79WuS0NSwAAAgESAAA"
sharing_sync_status: "Synced"
show_completed: false
sort_asc: true
sort_type: 1
theme: "blue"
title: "タスク"
}
sync
{
id : "sync-key"
queue : [
{
data :
committed_day : {date_time: "2018-04-06", time_zone: "Asia/Tokyo"}
id : "l-5hkdu"
list_id : "inbox"
local_id : "l-5hkdu"
position : 1492520890000
postponed_day : null
remote_id : undefined
remote_list_id : "AQMkAwATM0MDAAMS1hZGNiLTQzYjYtMDACLTAwCgAuAAADVFc0lFz6P0m-xARjTHHhrAEAXAI-lv8jBkOPt79WuS0NSwAAAgESAAAA"
title : "aaaa"
today_position : 1522984086542
type : "CREATE_TASK"
}
]
length : 1
}
- sync-keyという1レコードのみ
- queueが合って、typeとdataがセットになったデータが入ってる。fluxのアクション的なノリ
- オンラインになると実行される
steps, members
この2つのテーブルに保存されているデータを見たことがない
membersはタスクの共有用なんだろうなとは思ったけど、UI上で共有する方法が分からない
おわり
- Firebase使ってアプリ書くとオンライン・オフライン対応してくれてキューとか意識しなくてよかったので、自前でやる時の参考になりそうだった。
- indexがkeyにしか振られてないので、まだlocalStorageの延長線上の使い方だなーという印象
- remote_idなどクライアントとサーバーをまたいだデータやりとりはWebエンジニアとしてはあまりやらないので、デスクトップやスマートフォン上での設計は学ぶ必要性が強くなっているように感じた。(ReactNativeとかPWAの文脈として)