最近は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回で軽く触れましたが、以下に再度記載します。
- OAuthを用いた認証
- フレンド一覧の取得
- ユーザーコンテンツ(タイムラインの書き込み、写真、イベント等)の取得、作成
- 各種情報の取得、その他
1のOAuthによる認証以外の各機能は、基本的にはFacebook Graph APIを通じてアクセスできます。
ここではFacebook Graph APIに関して詳しく説明しませんが、例としてFacebook CEOのMark Zuckerberg氏の情報をGraph API経由で取得してみます。以下のURLをブラウザで開くと、Mark Zuckerberg氏の基本情報がJSON形式で返ってきます。
http://graph.facebook.com/zuck

これは誰にでも公開されている情報でしたが、Mark Zuckerberg氏がFacebook上で公開している写真などはアクセストークンが無いと取得できません。 そのほか、Facebook APIの基本的な仕組みに関しては以下のページから各種情報を参照して下さい。
http://developers.facebook.com/docs/coreconcepts/
また、Graph 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側の処理に負荷が高くなってしまうため、このような制限があるものと思われます。
コード例
それでは、いくつかコード例を挙げながら説明していきます。
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'
どのようなテーブルがあるかは、リファレンスを参照して下さい。
複数テーブルからの情報の取得
次に、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のリファレンスページにある例ですが、あるイベントに招待されている人のプロフィールを取得します。参照すべきテーブルはprfileとevent_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を送信します。
なお、上の例ではquery1、query2という名前でしたが、任意の名前を付けることができます。また、ここに限った話ではありませんが、送信するデータは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に対応。