[MBaaS][Data Store] Parseで簡単モバイルバックエンド構築 – [データストアの特殊な型]
前回の続き
前回にデータストアの基本的な型(String, Number, Booleanなど)を紹介しました
今回はParse独自のちょっと特殊な型を紹介します
特殊な型
以下では特殊な型について紹介していきます。
ここでは例として、
「記事のエントリを格納するためのカスタムクラス【Entry】と、執筆者情報を格納するための【User】」を設定してみましょう。
登場人物になるクラスは次の2つです。
Pointer
One-to-Many Relationships. When you’re thinking about one-to-many relationships and whether to implement Pointers or Arrays, there are several factors to consider.
説明にあるように1:1や1:多の関係を使いたい場合に利用します。
前回のサンプルでしれっと使っていましたが、【createdBy】カラムの型がPointerになります。
このPointerで示されているUserは、記事の執筆者としてUserクラスの1つのオブジェクトを指しています。
図解
こんな感じ。このEntryを作成したユーザー情報が「createdBy」に格納されているので、そのポインターを辿ると作成したユーザー情報の詳細を取得できます
Data Browserで確認してみます。「createdBy」のデータがリンクになっているのが分かります。
リンクをクリックしてみると
Pointerで指定されているオブジェクトへ飛ぶことができました。Entryオブジェクトに対して1つのUserオブジェクトがPointerで紐づけられているようです。
用途
基本的には、1つのオブジェクトに対して別クラスの特定の一つのオブジェクトを指したい場合に利用すれば良いようです。
1:多の関係も構築できるので、1つのカラムに対して複数のオブジェクトをPointerとして指定することも可能です。
Relation
Many-to-Many Relationships. Suppose we had a book reading app and we wanted to model Book objects and Author objects.
こちらは、多:多の関係を使いたい場合に利用します。ちょっとよく分からないので解説の続きを見てみると例が載っています。
As we know, a given author can write many books, and a given book can have multiple authors.
書籍と著者の関係を例に挙げているようです。
図解してみます
Bookは著者としてAuthorクラスのオブジェクトを複数持ちます。
このRelationに対してQueryを実行することが可能です。これはPointerでは実現できない動作です。
こういった場合に有効なようです。
フォロー、フォロワーの関係などはPointerで考えると複雑になるので、Relationで解決すべき例の一つですね。
GeoPoint
Parse allows you to associate real-world latitude and longitude coordinates with an object. Adding a GeoPoint data type to a class allows queries to take into account the proximity of an object to a reference point.
基本的には緯度・経度を持ったオブジェクトです。このままだと何が美味しいのかよく分かりません。
そのまま数値を格納しておくだけで良いじゃないですかっ!
何が良いの?
ParseにはGeo Queryという機能があります。これを利用すると位置情報を超強力にサポートしてくれます。
様々な条件に対して自前で緯度経度から地球の球体やらを考慮した計算式を組み込むのは非常に面倒な上、バグを埋め込む要因になるので、この辺をSDKがサポートしてくれるのは非常に助かります。
例えばこんな場合
ある地点の緯度経度から、半径4km以内に存在するオブジェクトをリスト化しようと思ったとき、
コードで書こうと思うと、全オブジェクトに対して現在地点からの距離を計算しなきゃいけないなど、かなり面倒です。
Geo Queryを利用してみましょう。こんな感じになります。
import json,httplib,urllib connection = httplib.HTTPSConnection('api.parse.com', 443) params = urllib.urlencode({"where":json.dumps({ "location": { "$nearSphere": { "__type": "GeoPoint", "latitude": 30.0, "longitude": -20.0 }, "$withinKilometers": 4.0 } })}) connection.connect() connection.request('GET', '/1/classes/PlaceObject?%s' % params, '', { "X-Parse-Application-Id": "<your-application-id>", "X-Parse-REST-API-Key": "<your-rest-api-key>" }) result = json.loads(connection.getresponse().read()) print result
このQueryは"「緯度30、経度-20」を中心に4キロメートルの円内にある情報を全て取得する"となります。
これだけで該当するポイントの情報リストを取得することができます。
位置情報を、あいまいな条件検索をQueryで一発で引けるのは大きなメリットだと思います(バグを埋め込む確率も減るし)
ACL
最後にACLをさらっと。ACLは「Access Control Lists」の略です。アクセス制御を司るちょっと特殊なオブジェクトになります。
こちらは、全てのオブジェクトに初期カラムとして設定されます。データの中身は単純なJSONで記述されています。
ユーザーデータを一つ作成し、確認してみます。
{ "*": { "read": true }, "HjFHc7hZ4q": { "read": true, "write": true } }
二つのJSONデータが確認できます
まずは一つ目
"*": { "read": true },
これは、Roleに対するPermission設定となります。
ここにRole名を指定するとそのRoleに紐づくユーザーであれば、アクセスすることが可能です。
ここでは「*」が指定されています。これはどのRoleでもRoleに所属していなくてもアクセス可能なPublicアクセスを示します。
そのため、このデータはどのユーザーでも読み取ることができるデータとなります。当然、write権限はないので書き込み権限はありません。
続いて二つ目
"HjFHc7hZ4q": { "read": true, "write": true }
これは、そのオブジェクトのオーナー情報になります。
この場合は「HjFHc7hZ4q」というObject IDを持つUserがオーナーとなっています。
こちらはRead権限に加えて、Write権限も付与されているのでオブジェクトに対してCRUDの全ての操作が可能です。
まとめ
以上で、Parseにおけるデータストアを利用するうえでの大まかな知識は確認できました。
- Pointerは、1つのオブジェクトに対し何らかの関係情報を持たせたい場合に利用する
- Relationは、こちらもオブジェクトに対し何らかの関係情報を持たせたい場合に利用する。多:多の関係性が必要になる場合、相互に関係を持ち合う場合など
- GeoPointは、位置情報を扱う。GeoQueryという特殊なQueryを利用して位置情報を非常に簡潔に扱うことができるため、積極的に使っていくべし
- ACLは、オブジェクトへのアクセス制御を司る。Roleのアクセス制御とオーナーの権限を記述することで、アクセス可否を制御できる
次はようやく待ちに待ったCloud Codeです。自分がParseの魅力にハマった要因の一つです。
以上、Parseにおける特殊な型でした