Contributors Post

Webサービスにおける外部APIの使用(その3) - Facebook Query Language

|

最近はFacebookのユーザー、Facebookアプリの数が増えています。本記事では、はじめにFacebook APIについて簡単に説明した後、Facebookが持っている情報を効率的に取得するためのFacebook Query Language(FQL)について説明します。

はじめに

昨年から日本でもFacebookユーザーが爆発的に増加しています。最近のWebアプリの多くはFacebookとの何らかの連携機能を持っていて、連携機能を持っていないものを探すほうが難しいかもしれません。

Facebook APIには多くの機能があるのですが、今回はその1つであるFacebook Query Language(以下FQL)について説明します。

なお本記事は、読者に以下の前提知識がある事を想定しています。

  • Facebookの基本的な仕組み
  • Facebookアプリ、Graph APIの基本的な仕組み
  • Facebook SDKを使える程度のプログラミング知識

またテスト用のFacebookアプリをあらかじめ作成しておき、開発環境にFacebook SDKをダウンロードしておくとよいと思います(言語は問いません)。

Facebook API

FQLについて解説する前に、まずはFacebook APIについて簡単に紹介しておきます。

Facebook Graph API

Facebookと連携して何ができるかに関しては、第1回で軽く触れましたが、以下に再度記載します。

  1. OAuthを用いた認証
  2. フレンド一覧の取得
  3. ユーザーコンテンツ(タイムラインの書き込み、写真、イベント等)の取得、作成
  4. 各種情報の取得、その他

1のOAuthによる認証以外の各機能は、基本的にはFacebook Graph APIを通じてアクセスできます。

ここではFacebook Graph APIに関して詳しく説明しませんが、例としてFacebook CEOのMark Zuckerberg氏の情報をGraph API経由で取得してみます。以下のURLをブラウザで開くと、Mark Zuckerberg氏の基本情報がJSON形式で返ってきます。

http://graph.facebook.com/zuck

fig-fql-01.png

これは誰にでも公開されている情報でしたが、Mark Zuckerberg氏がFacebook上で公開している写真などはアクセストークンが無いと取得できません。 そのほか、Facebook APIの基本的な仕組みに関しては以下のページから各種情報を参照して下さい。

http://developers.facebook.com/docs/coreconcepts/

また、Graph APIで取得できる情報の詳細に関しては、以下のページを参照して下さい。

http://developers.facebook.com/docs/reference/api/

Facebook Query Language(FQL)とは

FQLとは、その名から想像がつく通りSQLに似た問い合わせ言語で、Graph APIで取得できる情報を通常のGraph APIでより複雑な条件で問い合せる事が可能です。Graph APIのラッパーという見方をしてもいいかもしれません。詳しくは次節以降で見ていきます。

FQLの機能

FQLの機能は大きく分けて以下の2つです。

  • SQLに似た文法で、Graph APIから情報を取得する
  • 複数のクエリを1度のAPI呼び出しで実行する

SQL風の問い合わせ

SQLのようにSELECT文で情報を取得できます。プログラマの方であればSQLはご存知だと思いますので、ここではSQLとの比較や制限事項を中心に説明します

複数のテーブルから問い合わせが可能
これはSQLでは基本的な機能ですが、FQLの場合はJOINが使えなません。ただし、IN句を用いたサブクエリ内で別のテーブルを参照することは可能です。
AND、ORの論理演算
SQLと同様、WHERE句の中でANDやORを使うことができます。
ORDER BY、LIMIT
これもSQLと同様です。
WHERE句の中には、「Indexable」なカラムを含む必要がある
RDBMS的な説明をすると、インデックスがついたカラムを検索条件に含めて、検索にインデックスが使われるようにする必要があります。

例えばuserテーブルから情報を検索する場合、以下のリンク先ページの「カラム一覧」で、Indexableに印が付いているカラム(uid, username, name)をWHERE句に含めなければいけません。この制限が無いと、RDBMSに例えるなら、10億レコード近くあるテーブルをテーブルスキャンする事になり、Facebook側の処理に負荷が高くなってしまうため、このような制限があるものと思われます。

http://developers.facebook.com/docs/reference/fql/user/

複数のクエリの実行

Facebook APIを使ってみると分かりますが、1度のAPI呼び出しで値が返ってくるまでには、1秒あるいはそれ以上かかります。従って、APIの呼び出し回数は極力少なくする必要があります[1]

通常のGraph APIであれば複数回APIを呼びださなければいけなかったケースが、上で説明したIN句を使ったサブクエリでは1つのFQLで完結します。ただ、それでも対応できないケースでは、複数のFQL文を1度のAPI呼び出しで実行することができます。

[1]前回まで説明したキャッシュも対策の1つです

コード例

それでは、いくつかコード例を挙げながら説明していきます。

FQL呼び出しの基本

Facebook SDKを使ってAPIを呼び出す部分は各言語によって多少異なりますが、仕組みとしては大体どれも同じです。ここでは、PHPで簡単な例を以下に記載します。

// Facebook SDKのクラスのインスタンスを生成
$facebook = new Facebook(array('appId'  => 'YOUR APP ID',
                               'secret' => 'YOUR APP SECRET',
                               'cookie' => true,
                               ));
// 実行するFQL
$fql = "SELECT uid2 FROM friend WHERE uid1 = me()";
// API呼び出し
$result = $facebook->api(array('method' => 'fql.query',
                               'query' =>$fql,
                               'access_token' => 'USER`S ACCESS TOKEN',
                               ));

この例では、そのユーザー(アクセストークンの持ち主)のFacebookフレンドのユーザーID一覧を取得します。

これはFQLに限った話ではありませんが、以下のような注意点があります。

  • 問い合わせるデータの種類によって、上の例のようにユーザーのaccess tokenが必要です。
  • そのユーザーから適切なパーミッション取得をしていないと、結果が返ってきません(この場合、特にエラーは返ってこないで空の結果が返ってくるようです)。

基本的なFQL

単一のテーブルからデータを取得するFQLに関しては、特に問題ないと思います。例えば、Mark ZuckerbergのユーザーIDとフルネームを取得するFQLは以下のようになります。

SELECT uid, name FROM user WHERE username = 'zuck'

どのようなテーブルがあるかは、リファレンスを参照して下さい。

http://developers.facebook.com/docs/reference/fql/

複数テーブルからの情報の取得

次に、IN句を使って複数のテーブルから情報を取得する例を説明します。以下のFQLは、そのユーザーの友達の中から、そのアプリを使っている友達のみを抽出します。

SELECT uid, name, pic_square FROM user
WHERE uid in (SELECT uid2 FROM friend WHERE uid1=me()) AND is_app_user = 1

以下、FQL特有の点を少し補足します。

me()は、アクセストークンの持ち主(通常はログインしているユーザー)を表します。 また、is_app_userは、そのユーザーがあなたのFacebookアプリ(上に示したPHPのコードではappIdで指定したアプリ)を使っているかどうかを表します。

複数のクエリの実行

前の例ではIN句を使って、複数のテーブルに対する問い合わせを行いました。次に、1つのFQL文では取得できない情報の例を2つほど説明します。

まずは、FQLのリファレンスページにある例ですが、あるイベントに招待されている人のプロフィールを取得します。参照すべきテーブルはprfileevent_memberテーブルです。

通常のSQLであればJOINを使って以下のように書けますが、FQLではJOINが使えません。

-- SQL
SELECT p.name, p.url, p.pic, em.rsvp_status
  FROM profile p
  JOIN event_member em ON em.uid = p.id
 WHERE em.eid = 1234678

従って、まずは以下のFQLでイベント招待者の一覧を取得します。

-- query1
SELECT uid, rsvp_status FROM event_member WHERE eid=12345678

次に、FQLで取得したユーザーIDの一覧を使ってプロフィール情報を取得します。具体的には以下のようになります。

-- query2
SELECT name, url, pic FROM profile WHERE id IN (SELECT uid FROM #query1)

これらのクエリをAPIに送信する場合には、以下のような形式のJSONを送信します。

なお、上の例ではquery1query2という名前でしたが、任意の名前を付けることができます。また、ここに限った話ではありませんが、送信するデータはURLエンコードする必要があります[2]

PHPでのコード例は以下のようになります。

$query1 = "SELECT uid, rsvp_status FROM event_member WHERE eid=12345678";
$query2 = "SELECT name, url, pic FROM profile WHERE id IN (SELECT uid FROM #query1)";
$queries = json_encode(array("query1" => $query1, "query2"=> $query2));
$result = $facebook->api(array(
                               'method' => 'fql.multiquery',
                               'queries' => $queries,
                               'access_token' => $access_token,
                               ));
[2]通常はFacebook SDKやHTTPライブラリ等で自動でやってくれますが、手動でGETリクエストを組み立てる場合などは考慮する必要があります

イベント関係でもう1つ例を挙げます。今度は、あるユーザーのイベント情報一覧を、出欠情報を含めて取得してみます。SQLであれば以下のように書けると思います。

-- SQL
SELECT e.eid, e.name, em.rsvp_status
  FROM event e
  JOIN event_member em ON e.eid = em.eid
 WHERE em.uid = me()

FQLでは、まず以下の通り自分のイベント一覧と出欠情報を取得します。

-- FQL1
SELECT eid, rsvp_status FROM event_member WHERE uid = me()

次に、イベントの詳細情報を取得します。

-- FQL2
SELECT eid, name, start_time, end_time
  FROM event
 WHERE eid IN (SELECT eid FROM #FQL1)

まとめ

日本でも、最近になってFacebookユーザーが爆発的に増加しており、Facebookにはユーザーに関する膨大な情報が詰まっています。通常のFacebook Graph APIであれば2回以上API呼び出しが必要なケースも、FQLを使う事により一度で効率的に取得する事ができます。

執筆者紹介
鹿島和郎
ソーシャルグルメサイト「Retty」の開発・インフラ全般を担当。過去には米企業でのオフショア開発拠点の立ち上げから国内SIerでの運用保守業務まで、広く浅く経験している何でも屋。
Rettyは、「行った」お店の投稿・共有、友達・趣味嗜好の合う人のオススメから「行きたい」お店をリスト化、スマートフォンで現在地周辺のお店をリストから検索などできるサービスで、Facebook、Twitterアカウントがあれば無料で使用可能。PC、iPhone、Androidに対応。

アーカイブ