SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Google App Engineで開発するスケールするアプリケーション

Google App Engineで開発するスケールするアプリケーション(後編)

Google App EngineとTwitterの連携アプリケーション構築

  • X ポスト
  • このエントリーをはてなブックマークに追加

オススメユーザー表示処理

 ここまで、Twitter APIにアクセスしユーザデータを収集する処理について説明してきましたが、次はいよいよオススメユーザーを画面に表示する処理のについて説明していきます。

オススメユーザーデータ作成処理

 オススメユーザー表示処理は、ユーザデータからオススメユーザデータを抽出する「オススメユーザーデータ作成処理」とオススメユーザを画面に表示する「オススメユーザ表示処理」の大きく2つに分かれます。まずは「オススメユーザデータ作成処理」のソースから説明します。処理概要は中編の図10などを参照してください。

リクエスト受付画面

 オススメユーザ作成処理は、図1のようなリクエスト受付画面(index.html)からPOSTでリクエストを受け付けます。

図1 リクエスト受付画面
図1 リクエスト受付画面

オススメユーザ作成リクエスト受付ハンドラ

 リクエスト受付画面では、オススメユーザ抽出対象のscreen_nameを入力します。オススメユーザデータを新たに抽出したい場合は、チェックボックスにチェックをいれます。「送信」ボタンが押下された場合に起動されるリクエストハンドラを以下に示します。

リスト13 main.py DispRecommendData postメソッド
class DispRecommendData(webapp.RequestHandler):

    def post(self):
        # screen_nameを取得
        screen_name = self.request.get('sn')
        
        # ~中略
        
        # 以下の場合、オススメユーザデータ作成処理要求をキューに格納する
        # ・RecommendUserエンティティが存在しない
        # ・データクリア指定のチェックボックスがチェックされた
        rec_user = RecommendUser.get_by_key_name(screen_name)
        clear_data = self.request.get('clear_data')
        if rec_user == None or clear_data == '1':
            # Task Queue にエンキューする
            _enqueue_make_recommend_user(screen_name)
            
            # メッセージを表示して終了する
            self.response.out.write(screen_name + ' enque task for ' + screen_name + '.please back to top page and wait a minute.')
        else:
            # RecommendUserに格納された情報をHTMLに表示する
            _disp_recommend(self,tw_user,rec_user)

RecommendUserエンティティ

 TaskQueueで抽出したオススメユーザのデータは、RecommendUserというエンティティに保存します。RecommendUserはscreen_nameをkey_nameとしてkey_nameのオススメユーザのscreen_nameの集合をscreen_name_listに格納します。screen_nameは文字列なので、db.StringListPropertyを使用します。

リスト14 models.py RecommendUserクラス
class RecommendUser(db.Model):
    key = db.Key()
    screen_name_list = db.StringListProperty()

TaskQueue格納処理

 DispRecommendDataのpostメソッドでは、RecommendUserが存在しない場合は、_enqueue_make_recommend_userメソッドを呼び、画面で入力されたscreen_nameのユーザにオススメのデータを作成するためのTaskを生成しTaskQueueに加えます。ソースを以下に示します。

リスト15 main.py _enqueue_make_recommend_userメソッド
def _enqueue_make_recommend_user(screen_name):
    
    # 処理対象seqの上限seq値
    tw_user_cur_seq = Counter.current_id('IdGetTwitterUserSeq')

    threshold = 10               # オススメと判定する一致数の閾値
    proc_unit_num = 20           # Task処理1回のデータ抽出数
    lower_seq = 1                # TwitterUser.seqの抽出下限値
    upper_seq = proc_unit_num    # TwitterUser.seqの抽出上限値
    while 1:
        taskqueue.add(url='/mrd',
            params={
                'screen_name':screen_name,
                'lower_seq':str(lower_seq),
                'upper_seq':str(upper_seq),
                'threshold':str(threshold),
            }
        )
        # 処理対象seqの上限値を超えた場合、ループを抜ける
        if tw_user_cur_seq < upper_seq: break
        lower_seq += proc_unit_num
        upper_seq += proc_unit_num

 TaskQueueにTaskを追加するtaskqueue.addメソッドの引数には、さまざまな引数を指定することができます。urlパラメータには、Taskとして起動されるリクエストハンドラのパスを指定し、paramsパラメータには、Taskに渡すパラメータを辞書形式で指定しています。

Task処理

 TaskQueueのタスクは、リクエストハンドラのpostメソッドが起動されます。Taskとして起動されるMakeRecommendDataクラスのpostメソッドを以下に示します。

リスト16 main.py MakeRecommendData postメソッド
class MakeRecommendData(webapp.RequestHandler):
    # TQとして起動される処理
    def post(self):
        screen_name = self.request.get('screen_name')    # 抽出処理対象scree_name
        lower_seq = int(self.request.get('lower_seq'))   # 下限seq
        upper_seq = int(self.request.get('upper_seq'))   # 上限seq
        threshold = int(self.request.get('threshold'))   # オススメと判定する一致数の閾値

        # 処理対象ユーザデータ取得
        target_user = TwitterUser.get_by_key_name(screen_name)

        # --- 中略 ---

        # Queueで指定されたseqの範囲でTwitterUserエンティティを取得する
        q = db.GqlQuery("SELECT * FROM TwitterUser WHERE seq>=:1 AND seq<=:2",lower_seq,upper_seq)
        tw_users = q.fetch(upper_seq - lower_seq + 1)

        target_friends_set = set(target_user.friend_ids)

        match_screen_name_list = []
        for tw_user in tw_users:
            # 以下の場合は処理対象外
            # ・フォローしているユーザがいない場合
            # ・本人の場合
            # ・既にフォローしている場合
            if (len(tw_user.friend_ids) == 0 or tw_user.twid == target_user.twid) or tw_user.twid in target_user.friend_ids:
                continue

            friends = tw_user.friend_ids
            
            # フォローしているユーザが一致した数
            match_cnt = len(target_user.friend_ids) - len(target_friends_set-set(friends))

            # 閾値以上の場合「オススメ」とみなす
            if threshold <= match_cnt:
                match_screen_name_list.append(tw_user.screen_name)

        _put_rec_user(target_user.screen_name,match_screen_name_list)

 RecommendUserエンティティをDatastoreに保存する処理は_put_rec_userメソッドに実装されています。この処理は複数のTaskから並行で呼ばれる可能性がある処理のため、Counterクラスでも説明したdb.run_in_transactionの仕組みを使って、RecommendUserエンティティのトランザクションを保証しています。ソースを以下に示します。

リスト17 main.py _put_rec_userメソッド
def _put_rec_user(target_screen_name,screen_name_list):
    def txn():
    
        # 既存エンティティの取得
        user = RecommendUserData.get_by_key_name(target_screen_name)
        if user == None:
            user = RecommendUserData(key_name=target_screen_name)

        # リストを連結する
        sn_list = user.screen_name_list + screen_name_list

        # 重複を省いてからエンティティにセットする
        s_list = list(set(sn_list))
        user.screen_name_list = list(set(sn_list))
        user.put()
    return db.run_in_transaction(txn)

次のページ
まとめ

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
Google App Engineで開発するスケールするアプリケーション連載記事一覧

もっと読む

この記事の著者

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

WINGSプロジェクト 佐藤 治夫 (株式会社ビープラウド)(サトウ ハルオ)

WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS Twitter: @yyamada(公式)、@yyamada/wings(メンバーリスト) Facebook

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/5023 2010/04/19 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング