というようなことをする為にクエリを書く。もっと良い書き方があるような気もする。
StackOverFlowを見たらRankを使おうみたいなことが書いてあったけど、サンプルがうまく動かなかったのでROW_NUMBERを使用。0.11以降実装されているらしい。
下記クエリの仕様は、page_id, user_idが記述されているアクセスログ的なテーブルを集計して、各page_idを訪れているuser_id上位10件を出すものとする。page_idはurl encodeする。
SELECT REFLECT("java.net.URLEncoder", "encode", page_id), COLLECT_ALL( user_id ) FROM ( SELECT page_id, user_id, ROW_NUMBER() OVER ( PATITION BY page_id ORDER BY cnt DESC ) AS rank FROM ( SELECT page_id, user_id, COUNT(1) AS cnt FROM access_log GROUP BY page_id, user_id ) a DISTRIBUTE BY page_id, user_id ) b WHERE rank <= 10 GROUP BY page_id, user_id
実際に動かしたクエリからいろいろ改変しているので、このままだと動かないかもしれない。でもイメージはだいたいこんな感じで想定した動きになった。
以下、使っている機能の説明。
REFLECT : Javaのメソッドを直接呼び出す。int, double, string等の基本的なクラスしか引数に渡せない。 COLLECT_ALL : GROUP BYした結果をarrayに展開する。類似の機能にcollect_setなどもある。 ROW_NUMBER : 名前の通りROWにNUMBERを振る。 DISTRIBUTE BY : 同一のReducerで処理するよう指定する。