通常のRDBMSの場合、1対多のデータ構造を考えるとテーブルを二つ用意するのが一般的でしょう。しかしスキーマレスのデータベースの場合、そのような正規化よりもデータの扱いやすさを優先することが多くなります。
NCMBにおいてもそれは同様で、データストアでは数値や文字列、日付などの一般的なデータ形式に加えてJSONオブジェクトや配列なども登録できるようになっています。そして、それらのデータ型はSDKを使うことで容易に操作できるようになっています。
ただし、幾つかの注意点があります。今回は特にJavaScript SDKにおける注意点を紹介します。
配列の追加時
JavaScript SDKではaddメソッドを用意しています。
item.add('array', '追加するデータ');
これを使うことで現在の配列(今回はarrayカラム)の状態を気にすることなく要素を追加できます。もし配列の要素がユニークであって欲しい時には addUnique を使います。
item.addUnique('array', '追加するデータ');
要素を削除する場合は remove を使いします。
item.remove('array', '削除するデータ');
これらのメソッドは {"_op": "add"}
といった専用の機能を使ってデータを更新するものになります。add/addUnique/removeを実行した段階ではまだデータは更新されませんので、この後必ず update メソッドを実行する必要があります。 update メソッドであるというのは一つ大きな注意点です。データの新規登録時にはこれらのメソッドは使えませんので注意してください。
さらに返却値にも注意が必要です。add/addUnique/removeメソッドを実行しても、JavaScript上のオブジェクト(今回はitem)のarrayカラムのデータは更新されていません。基本的にデータストア上の内容を確認せずに配列要素の追加、削除ができるメソッドと考えるのが良さそうです。
データの新規登録時
まだデータが存在しない場合、item.array
はundefinedになる点に注意してください。 fetchAll()
を使った場合、結果データのlengthメソッドは0になります。しかし配列カラムの内容を使ってループ処理を行おうと考えている場合、undefinedでデータが取得してしまう可能性があります。
上記のように配列カラムのデータが更新されませんので、小さな配列の場合は item.array の状態を調べてデータ操作を行うのが良いでしょう。以下の例のように todo.tasks
が配列で存在している場合、JavaScriptのpushが使えます。データがない場合は配列として初期化する必要があります。
const task = $('#todo').val(); if (todo.tasks) { todo.tasks.push(task); }else{ todo.tasks = [task]; } todo.set('tasks', todo.tasks);
set
メソッドを使ってデータをまるごと入れ替えてしまう場合は保存後に todo.tasks へアクセスしても希望した通りのデータが入っています。小さな配列データを扱う場合にはこちらの方が使い慣れた形で扱えるはずです。
配列データはインデックスの問題であったり、並び替えなどで融通が効かないので慣れるまでついつい別クラスにしたくなることでしょう。しかしポインターを使いすぎたりするとデータストアの速度が遅くなったり、APIアクセス数が増えてしまいがちです。
配列カラムを使いこなしでmBaaSらしいデータの扱い方にトライしてください。