ラベル Twitter API の投稿を表示しています。 すべての投稿を表示
ラベル Twitter API の投稿を表示しています。 すべての投稿を表示

2010-07-03

OpenSocial Pages のタイムラインは AppEngine for Java の Data Store でどのように実現しているか

こんにちは。Nobuhiro Nakajima です。

OpenSocial Pages for Google Apps は OpenSocial Activities API という Twitter でいうところのタイムライン API を備えています。また Activities は Twitter でいうところの Friends (Following)、Lists、Mentions という人と人の関係(ソーシャルグラフ)で絞り込めるようになっています。


OpenSocial Pages は Google AppEngine for Java でホストしています。そして Activity の格納と検索は Data Store (JDO) で実現していて、エンティティの主な構造は、次のようにしています。

エンティティの構造

Twitter でいうところの User を表すエンティティです。この User が、誰に Follow されているか、どのグループに属するかを保持させています。
public class User {
  private String id;
  private Set<String> followerIds; // 誰に Follow されているか
  private Set<String> groupIds; // どのグループに属するか
}
Twitter でいうところの Lists を表すエンティティです。
public class Group {
  private String id;
}
Twitter でいうところの Status を表すエンティティです。この Activity が誰のもので、誰が関係するのか保持させています。followerIds と groupIds は Person のコピーを保持させています。mentionIds は Twitter でいうところの、テキスト中の @username で引用された User たちを保持させています。
public class Activity {
  private Long id;
  private String userId; // Person#id
  private String title; // テキスト
  private Set<String> followerIds; // Person#followerIds のコピー
  private Set<String> groupIds; // Person#groupIds のコピー
  private Set<String> mentionIds; // テキスト中の @username たち
}
Follow と Unfollow

User A が User B を Follow するとき、User B の followerIds に User A の userId を追加します。また Unfollow するときは、User B の followerIds から User A を除外します。

Group の参加と退会

User が Group に参加するときは、User の groupIds に自身の userId を追加します。また、退会するときは、User の groupIds から 自身の userId を除外します。

Activity の送信

送信する User の followerIds と groupIds を Activity の followerIds と groupIds にコピーして格納します。さらに、テキスト中の @username に該当する User の userId を mentionIds に格納します。

検索クエリ

User の Activity を検索するときは、Activity エンティティに対して、次のフィルタを使っています。
Query#setFilter("userId == :userId");
User が Follow している Friends の Activity を検索するときは、次のフィルタを使っています。このときの userId は、自分自身の ID を指定します。
Query#setFilter("followerIds == :userId");
Group に所属している User たちの Activity を検索するときは、次のフィルタを使っています。
Query#setFilter("groupIds == :groupId");
User が関係する Activity を検索するときは、次のフィルタを使っています。
Query#setFilter("mentionIds == :mentionId");

Activity の再構築

User A が User B を Follow したとき、User B の 全 Activity (*1) の followerIds に User A の userId を追加します。また Unfollow したときは、followerIds から除外します。

User が Group に参加するときは、User A の 全 Activity (*1) の groupIds に Group の groupId を追加します。また、退会したときは、groupIds から除外します。

前者と後者とも Task Queue を使って Activity を更新しています。

利点と欠点、そして課題

まず、基本方針は、シンプルなデータ構造とすること、そして、参照のコストを均一化するの(と削除)を最優先にしました。

この方法は、どんなに User が増えて、どんなに Follow したり、Group に参加したりしても、検索クエリのコストは一定なのが利点です。ただし、Follow/UnFollow、Groupの参加/不参加が発生したとき、過去にさかのぼって Activity を再構築する必要があるのが、大きな欠点です。

Activity がいくら蓄積されようとも、Activity 自体のコピーは保持していないため、Activity の削除は用意というのも利点です。ただ、User 自体を削除したとき、その User の 全 Activity を削除する必要がありますが、現状は削除せず、残したままとしています。

*1 Activity はどんどん蓄積されるものなので、時間が経過するにしたがって、全 Activity を更新するのは、現実的に難しくなってきます。そこで OpenSocial Pages では、新しいものの内 n 件分、もしくは n 日分の Activity のみ再構築の対象にするように妥協しています。古い Activity は重要度が低いよねという考え方です。

できれば、古い Activity もすべて再構築したいというのが課題です。古い Activity は即時で再構築することは絶対条件ではないため、バッチ的なものや、無駄な再構築が起こらないようにスケジューリングするとかいった方法でもよさそうです。

何かよいアイディアはないものでしょうか? エンティティグループとか、エンティティのエンティティとかうまく使えば、別の方法があるのかもしれないです。

2008-05-07

Twitter.statuses.join(BLOGRANGER::TG)

オートタギングAPI を使ってブログのエントリを勝手に分類してみる
BLOGRANGER TG のブログパーツで、このブログのミニ地図が表示できなかったので、手始めに BLOGRANGER API の オートタギング API というのを使って、指定したブログのエントリからタグを自動推定して、そのタグごとにエントリを分類して表示するアプリケーションを作ってみました。
さらに続けて、BLOGRANGER API の オートタギング API を使った別のアプリケーションを作ってみました。次のリンクからどうぞ。

Twitter.statuses.join(BLOGRANGER::TG)

今回は Twitter API を使いました。Twitter API で public_timeline を拾い続けて、そのユーザのアイコンを並べて表示していきます。このとき同時に、オートタギング API を使って、"つぶやき" のテキストからタグを自動推定します。そして、同じタグが推定された "つぶやき" 同士をくっつけて、アイコンをグループ化します。

↓こんな感じです。黒い枠で囲まれたアイコンが、同じタグが推定された "つぶやき" を表します。つまり、同じ話題について "つぶやいた" であろうユーザのアイコンが並んで表示されることになります。アイコンをクリックすると "つぶやき" の内容を表示しますので、気になるグループがあったら確認してみるとよいでしょう。



同じタグが推定されて "つぶやき" をくっつけるとき、推定されたタグをアニメーションでちょっと大げさに表示します。↓こんな感じです。"リアル" というタグで "つぶやき" がくっついたことを表しています。



↓は "絢香" というタグで "つぶやき" がくっついたことを表しています。



"つぶやき" が少ないうちは、なかなかくっつきませんが、"つぶやき" が増えてくると、タグの推定が連鎖してきて、アニメーションが慌しくなってきます。しばらくぼ~っと眺めてみてください。

Twitter API で public_timeline を拾う頻度を高くしたいのですが、オートタギング API は、それなりの計算量がありそう?なので、その負荷を考慮しています。オートタギング API を使って "つぶやき" からタグを自動推定するたびに、1秒のウェイトを入れています。そのため、拾いきれない "つぶやき" がかなり出てくると思います。

2007-10-09

Twitter API ガイドブック はアイディアいっぱいです

Twitter!―Twitter APIガイドブック を手に入れました。

単に Twitter API の和訳にとどまらず、Python、Ruby、Perl、Java、C/C++ のライブラリの紹介とサンプルプログラムも含まれています。

また Twitter API を使ったサービスやツールを数多く紹介していますので、Twitter API を使ってどんなことが実現できるのか把握しやすく、またアイディアを膨らませるのに役立ちます。

さらに Twitter や Twitter API の類似サービスの紹介と比較もあり、Twitter の特徴や位置づけを理解するのにも役立ちます。

Twitter!―Twitter APIガイドブック

Twitter API は JSONP をサポートしていますので JavaScript だけでも十分遊べます。