Parse終了のお知らせ。でもやってみる。
Parseサービス終了するらしい
UI好きだったので残念だ。いまReact Nativeで作っているアプリのために使う予定だったのだけど。 他のサービスや自分でサーバサイドを一から書くことを検討もしたけど、やっぱりこのままParse使ってみようと思う。
理由
- 終了まであと1年くらいある
- Parse Server(上記記事参照)などもでたので、こっちも使ってみたい
- まだParseというサービスの良し悪しを体感できるほど使えていない
- 移行作業もそれはそれでいい機会
Parseの特徴
- UserやRoleごとに細かいアクセス制御ができる
- 多対多の関連を表現するための関連テーブル(Parseでいうclass)はいらない
ParseReactについて
Seamlessly bringing Parse data into your React applications.
とあるので、ReactからParseを使うための実装かと。
Parse Javascript SDK との違い
READMEによると
Parse + React is an interface layer on top of the Parse JS SDK that provides simple access to the Parse API from React.
とあるので、Parse Javascript SDKをReactでラップしてくれているぽい。 ブラウザなどでのJSからの用途ではParse JS SDKをReact NativeからはParseReactを使う感じなんだと思う。 ReactNativeは、JSの実行環境が特殊だったりするので、そのための対応などだろうか。
今後の調べるべきこと
- ブラウザ(React)とReactNativeの実行環境の違い
実装されたAPI
データの取得やバインドのような機能を提供するAPIも独自に追加されている。 このobserveは確か多対多関連の参照でうまく動かなかった記憶があるので、後ほど検証する。
ParseNativeでParseを使う
一対多関連の表現
Author
とBook
を例にあげる。
一対多関連の選択肢
- Pointers
- Arrays
今回はPointersを使ってみる。
下記リンクによるとParse Relationsによる関連付けはwebからはできないらしいので、ParseダッシュボードのAPIコンソールから、実際の関連付けを行う。
エンドポイントは、
PUT classes/Book/AAA
で、これに対して、
{ "author":{ "__type":"Pointer", "className":"Author", "objectId":"BBB" } }
のようにauthor
カラムにidがBBB
のAuthor
をPointer
として紐付けている。カラムは自動で生成される。
これをReact Nativeから取得するには、
observe: function (props, state) { return { user: ParseReact.currentUser, books: new Parse.Query('Book').include('author') }; },
とすると、
{ id: { className: 'Book', objectId: 'AAA' }, className: 'Book', objectId: 'AAA', createdAt: ***, updatedAt: ,*** ACL: ***, author: { id: { className: 'Author', objectId: 'BBB' }, className: 'Author', objectId: 'BBB', createdAt: ***, updatedAt: ***, name: 'name' } }
のようにあるデータが取得でき、books.author.name
にアクセスできる。
include
についてはParseのREST API Guideに
Use on Pointer columns to return the full object
とあったので、Pointer型専用ぽい。JS SDKのDocsには特にそんな記述ない感じだけど、APIレベルでPointer型専用ならそうなんでしょう。
多対多関連の表現
Book
とAuthor
の多対多の関連を例にあげる。
上記ドキュメントによれば、次の3つの選択肢があるようだ。
多対多関連の選択肢
- Arrays
- Parse Relations
- Join Table
今回は、多対多関連の片方のオブジェクト数(Book
)が100以上になりそうなこと、
Book
とAuthor
に限れば、関連の作成日時などのメタデータは必要ないことからParse Relationsを選択する。
Arraysの選択時は、2016/02/04現在Pointer型の配列展開に関するバグが報告されているようなので注意が必要だ。
Parse Relationによる多対多の関連付け
エンドポイントは、
PUT classes/Book/AAA
で、これに対してQuery Parameter
{ "authors":{ "__op":"AddRelation", "objects":[{ "__type":"Pointer", "className":"Author", "objectId":"BBB" }] } }
でリクエストする。
これはidがAAA
のBookクラスのauthors
カラムに、idがBBB
のAuthorクラスをRelation型として関連付けることを表す。
カラムがなければ自動で生成される。
関連を含むデータを取得
ParseReactのobserveを使う
observe: function (props, state) { return { user: ParseReact.currentUser, books: new Parse.Query('Book') }; }
observeを使って、Book
データを取得する。
{ id: { className: 'Book', objectId: 'AAA' }, className: 'Book', objectId: 'AAA', createdAt: ***, updatedAt: ***, ACL: ***, authors: { parent: { _objCount: 9, className: 'Book', id: 'AAA' }, key: 'author', targetClassName: 'Author' }, }
取得できたBook
のあるデータを示す。
関連は持ってるぽいが、Author
のnameプロパティは直接取れていない。
new Parse.Query('Book').include('authors')
とかしたら、データが取得できなくなることからも、include
はやはりPointer型専用か。
authors: { parent: { _objCount: 9, className: 'Book', id: 'AAA' }, key: 'author', targetClassName: 'Author' }
これだけの情報じゃ、Authorテーブルからも引けないけどどうするんだ。
matchesQueryを使う
var query = new Parse.Query(Parse.Object.extend("Book")); var innerQuery = new Parse.Query(Parse.Object.extend("Author")); query.matchesQuery("authors", innerQuery); query.get("AAA", function(book) { console.log(subjectObj); });
{ className: 'Book', _objCount: 12, id: 'AAA' }
得られたのは、Book
クラスのParse.Object
っぽいが、
get('authors')
{ parent: { _objCount: 12, className: 'Book', id: 'AAA' }, key: 'authors', targetClassName: 'Author' }
authorsプロパティは取得できない。
innerQuery.exists('not_exists_property');
null
となることからも、matchesQuery
はBook
に対してもAuthor
に対してもクエリをかけてくれるようなものではなく、
ある条件を満たすクエリをBook
にかけるような挙動であると予測できる。
Parse.Relationを使う
new Parse.Query('Book').get('AAA').then(function (book) { book.relation("authors").query().find().then(function (authors) { console.log(authors); }); });
[ { _objCount: 11, className: 'Author', id: 'BBB' }, { _objCount: 12, className: 'Author', id: 'CCC' } ]
このような出力が得られるが、一見するとnameプロパティは含まれていないよう。
しかし、Parse.Object
からは.get
メソッドでプロパティを取得できる。
authors.map(function (x) { return x.get('name'); })
まとめ
多対多の関連の参照
Parse.Relation
を使った多対多関連を一つのクエリで参照することはできないらしい。
しかしParse.Relation使えば、複合的な記述にはなるが十分に使える。
observeについても、うまく複合クエリをセットできればちゃんと使えるのかも。
今後に生かすこと
JSのobject
と、Parse.Object
の区別がつかず、get
メソッドによるプロパティ取得に気付けなかったことが時間がかかった原因になった。typeof
やconsole.log
からはその違いが見つけづらかった。
それと英語をもっと速く読めるようになりたい。急がば回れだ。