データストアでは多対多の関係性を表現するのにリレーション機能が使えます。あるデータに紐付く多数のデータを管理します。
そんなリレーションはデータ作成時にも使えるのですが、mBaaSにはトランザクションがないので使い方に注意する必要があります。
実装例
例えば以下のような実装があります。ParentのデータがChildのデータを3件リレーションで連結しています。注意点として、child2だけ .set('date', new Date(undefined))
をしています。これは不正な日付なのでデータ保存時にエラーを起こします。
const Parent = ncmb.DataStore('Parent'); const Child = ncmb.DataStore('Child'); (async () => { const parent = new Parent; const relation = new ncmb.Relation(); const child1 = new Child; const child2 = new Child; const child3 = new Child; child1.set('name', '子要素1'); child2.set('name', '子要素2').set('date', new Date(undefined)); child3.set('name', '子要素3'); relation.add(child1).add(child2).add(child3); parent.set('children', relation); await parent.save(); console.log(parent); })();
この状態で保存するとどうなるでしょうか。
リレーションデータの保存について
この保存処理では、まずリレーションに結びつけられているデータから保存されます。つまり child1〜child3 が最初に保存されます。注意して欲しいのは、保存順番はネットワークの状態によってバラバラに行われると言うことです。試してみた限りではchild3、つまり最後に登録されたデータから保存されるようです。ただし非同期です。
そしてchild2でエラーが起きた時点で処理が停止します。この時、parentは保存されていません。かといってchild3は(場合によってはchild1も)保存された状態になっています。child1〜child3が保存された後、parentが保存されます。もしparentの保存に失敗した場合はchild1〜child3が残された状態になります。
データの状態について
もしデータが正常に保存された場合、parentとchild1〜child3は次のようになっています。
Data { createDate: '2019-10-18T06:17:10.096Z', objectId: '9ytyhNENNUyZwS6o' } Data { name: '子要素1', createDate: '2019-10-18T06:17:09.954Z', objectId: 'lc0ozCokrYKHmU3' } Data { name: '子要素2', createDate: '2019-10-18T06:17:09.955Z', objectId: 'lL6oJ7NrCXlujVhn' } Data { name: '子要素3', createDate: '2019-10-18T06:17:09.952Z', objectId: 'tiPqMTfG2WXwyRS' }
しかし1件でも保存に失敗すると次のようになります。parentが保存されていないのは良いのですが、child1〜child3のいずれかは保存されているにも関わらずobjectIdが入っていないので注意してください。
Data { children: Relation { __op: 'AddRelation', objects: [ Data { name: '子要素1' }, Data { name: '子要素2', date: { __type: 'Date', iso: null } }, Data { name: '子要素3' } ], relatingClass: '/classes/Child' } } Data { name: '子要素1' } Data { name: '子要素2', date: { __type: 'Date', iso: null } } Data { name: '子要素3' }
まとめ
リレーションの保存はデータを一括で送信している訳ではないので、個別にデータ保存を行った方が安全に見えます。特にどのデータが保存に失敗したか分からない状態なのはデータ管理上、問題になるかも知れません。実装時にはご注意ください。