• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
appengine ja night #24 Google Cloud Endpoints and BigQuery
 

appengine ja night #24 Google Cloud Endpoints and BigQuery

on

  • 4,777 views

appengine ja night #24で発表したGoogle Cloud Endpoints と BigQueryのスライドです。 ...

appengine ja night #24で発表したGoogle Cloud Endpoints と BigQueryのスライドです。

・English version
http://www.slideshare.net/vierjp/appengine-ja-night-24-google-cloud-endpoints-and-bigquery-english

Statistics

Views

Total Views
4,777
Views on SlideShare
4,513
Embed Views
264

Actions

Likes
13
Downloads
0
Comments
0

5 Embeds 264

https://twitter.com 231
http://blog.vier.jp 28
http://tweetedtimes.com 3
http://1104587451872577814_51902b932e290a6974ffb6ea1c41354a67beab66.blogspot.com 1
https://www.google.co.jp 1

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    appengine ja night #24 Google Cloud Endpoints and BigQuery appengine ja night #24 Google Cloud Endpoints and BigQuery Presentation Transcript

    • Google Cloud Endpoints & BigQuery appengine ja night #24Ryo Yamasaki @vierjp 1
    • 自己紹介 Ryo Yamasaki •  Blog •  http://blog.vier.jp/ •  Twitter •  @vierjp •  仕事 •  Javaでサーバーサイドの開発がメイン •  前職はスマホ向けサービス事業者の技術リーダー •  Google App Engineを中心にCloud StorageやBigQuery等、 Google Cloud Platformのプロダクトを利用していました。 •  個人でAndroidアプリ公開してます •  WiFi Tunes Sync 2
    • Google Cloud Endpoints 概要 3
    • Google Cloud Endpoints 一言で言えば・・・AppEngineをクライアントアプリのバックエンドとしてより簡単に使えるようにするための仕組み 4
    • Google Cloud Endpoints 通信周りの実装が不要になります Endpointsがカバーする範囲 クライアント サーバー側 GET・POSTパ 必要な値を リクエストを リクエストを ラメーターを 取得 送信 受け取る セット リクエスト内 サーバー側   API 容に基づい クライアント・ライブラリ Framework て処理 オブジェクト 取得した結 JsonをParse レスポンスを をJson形式 果を基に処 してオブジェ 受け取る に変換して 理を行う クトにセット 返す 5
    • Google Cloud Endpoints Android、iOS、JavaScript用クライアント・ライブラリを自動生成できる App  Engine   Cloud   Endpoints Android   iOS   JavaScript   6
    • Google Cloud Endpoints GoogleアカウントでのOAuth 2.0認証をサポート 7
    • Google Cloud Endpoints AppEngineの持つ各種サービスを利用可能 Cloud   Endpoints   AppEngine   Google  Cloud   Datastore   Url  Fetch   Mail   Task  Queues   Storage   8
    • Google Cloud Endpoints 作成したAPIはAPI Explorerから実行可能 •  Google APIs Discovery Serviceに準拠 •  OAuth2認証した状態でのAPI実行も簡単 API実行画面 API一覧表示画面 9
    • Google Cloud Endpoints 実装手順 10
    • Google Cloud Endpoints 必要な環境 (Java) •  Eclipse •  AppEngine SDK1.7.5以降 •  Google Plugin for Eclipse (最新) 11
    • Google Cloud Endpoints 実装手順 1.  Eclipseプロジェクトの作成 2.  サーバー側(バックエンド)の実装 3.  API ExplorerでAPIの動作確認 4.  クライアントライブラリの生成 5.  クライアント側の実装 12
    • Google Cloud Endpoints Eclipseプロジェクトの バックエンドの API  Explorerで クライアントライ クライアント側 作成 実装 動作確認   ブラリの生成 の実装 Androidクライアントを作る Androidクライアントを作ら 場合 ない場合 2.右クリックから AppEngineの 「Generate  AppEngine   1.Androidプロジェクトを作 「Webアプリケーションプロ Backend」 成 ジェクト」 でサーバー側プロジェクト を作成 作成 13
    • Google Cloud Endpoints Eclipseプロジェクトの バックエンドの API  Explorerで クライアントライ クライアント側 作成 実装 動作確認   ブラリの生成 の実装 @Api(name = "appData", version = "v1", description = "AppData API description v1") public class AppDataV1Endpoint { コード例 IDを指定してデータを1件取得する処理 @ApiMethod(name = "data.get", path = "data/get/{id}”) public AppDataV1 get(String id) throws ServiceException { @Named("id") String id) throws ServiceException { try { // Entityのget処理 Key key = KeyFactory.createKey("AppData", id); DatastoreService ds = DatastoreServiceFactory.getDatastoreService(); Entity entity = ds.get(key); // 返却するDTOを生成してEntityの値を詰め替える ・ポイント AppDataV1 result = entity2Dto(entity);  ・@Api、@ApiMethod、@Namedアノテーション return result;  ・例外をthrowして呼び出し元にエラーを通知する } } catch (EntityNotFoundException e) { // IDに対応するデータが見つからない場合のエラー処理 throw new NotFoundException("id:" + id + " is not found."); } catch (Exception e) { // 予期しないシステムエラーが発生した場合のエラー処理 throw new InternalServerErrorException(e); } } 14
    • Google Cloud Endpoints Eclipseプロジェクトの バックエンドの API  Explorerで クライアントライ クライアント側 作成 実装 動作確認   ブラリの生成 の実装 •  用意されているアノテーション •  @Api •  クラスに定義する •  API群の一つのバージョンを示す (ex. Google Drive API v1) •  一つのAPIを複数バージョン定義する場合は別のクラスにする •  @ApiMethod •  メソッドに定義する •  個別のAPIを示す (ex. Google Drive APIの「drive.files.list」) •  @Named •  メソッド引数に定義する •  @ApiMethodのPathで「引数との対応」を指定しないなら必須 •  Nullableを指定するなら必須 •  @Nullable •  メソッド引数に定義する •  メソッド引数の値としてNullを許可する場合に指定 15
    • Google Cloud Endpoints Eclipseプロジェクトの バックエンドの API  Explorerで クライアントライ クライアント側 作成 実装 動作確認   ブラリの生成 の実装 •  @Api @Api(name = "appData", version = "v1", description = "AppData API description v1”) ・JavaScript gapi.client.appData.data.get({id:$scope.id}).execute(function(response,rawResponseJson) { // callback }); ・Android AppData.Builder builder = new AppData.Builder(AndroidHttp.newCompatibleTransport(), new GsonFactory(), null); AppData appDataApi = CloudEndpointUtils.updateBuilder(builder).build(); AppDataV1 response = appDataApi.data().get(id).execute(); return response; 16
    • Google Cloud Endpoints Eclipseプロジェクトの バックエンドの API  Explorerで クライアントライ クライアント側 作成 実装 動作確認   ブラリの生成 の実装 •  @ApiMethod @ApiMethod(name = "data.get", path = "data/get/{id}”) @ApiMethod(name = "data.put", path = "data/put”) ・ポイント  ・nameはAPIExplorerに表示される名前や   クライアントライブラリのメソッド(関数)名に影響するので   ルールを決めてわかりやすい名前をつけると良いかと。  ・Pathは内部的に実行されるAPIのPathに影響する。   →気にしないなら定義しなくてもOK ・JavaScript gapi.client.appData.data.get({id:$scope.id}).execute(function(response,rawResponseJson) { // callback }); ・Android AppData.Builder builder = new AppData.Builder(AndroidHttp.newCompatibleTransport(), new GsonFactory(), null); AppData appDataApi = CloudEndpointUtils.updateBuilder(builder).build(); AppDataV1 response = appDataApi.data().get(id).execute(); return response; 17
    • Google Cloud Endpoints Eclipseプロジェクトの バックエンドの API  Explorerで クライアントライ クライアント側 作成 実装 動作確認   ブラリの生成 の実装 エラーの通知に使用できる例外クラス BadRequestExcepRon   • 入力エラー等 (ステータスコード400) UnauthorizedExcepRon   • 認証エラー (ステータスコード401) ForbiddenExcepRon   • アクセス権限が無い (ステータスコード403) NotFoundExcepRon   • 要求したデータが存在しない場合等 (ステータスコード404) InternalServerErrorExcepRon   • システムエラー等 (ステータスコード500) ServiceUnavailableExcepRon   • メンテナンス中 等 (ステータスコード503) 18
    • Google Cloud Endpoints Eclipseプロジェクトの バックエンドの API  Explorerで クライアントライ クライアント側 作成 実装 動作確認   ブラリの生成 の実装 •  例外クラスの自作 •  com.google.api.server.spi.ServiceException を継承 •  実装例 public class ConflictException extends ServiceException{ public ConflictException(String message){ super(409, message); } } 19
    • Google Cloud Endpoints Eclipseプロジェクトの バックエンドの API  Explorerで クライアントライ クライアント側 作成 実装 動作確認   ブラリの生成 の実装 •  ポイント •  API名(@Apiのname)は小文字から始める •  返り値としてリテラルは返せない。 •  返り値としてAppEngineのEntity型も返せない。 •  一覧取得処理でページングしたい場合は CollectionResponse<T>を使うと楽。 •  以下はメソッド引数として定義すれば取得可能。 •  javax.servlet.http.HttpServletRequest •  javax.servlet.ServletContext 20
    • Google Cloud Endpoints Eclipseプロジェクトの バックエンドの API  Explorerで クライアントライ クライアント側 作成 実装 動作確認   ブラリの生成 の実装 •  Tips:JUnitでサーバー側の単体テスト •  一般的なAppEngineアプリのクラスと同様に 単体テストコードを書くことができます。 •  Slim3のAppEngineTestCaseを使うのが簡単。 (実装コード内でSlim3を使ってなくてもOK) 21
    • Google Cloud Endpoints Eclipseプロジェクトの バックエンドの API  Explorerで クライアントライ クライアント側 作成 実装 動作確認   ブラリの生成 の実装 •  API ExplorerでAPIの動作確認 •  入力項目はフォームに自 動で反映されます •  赤字は必須項目 •  リクエスト内容を参照可能 •  実行結果も参照可能 •  OAuth2で認証してAPIを実 行することも可能 22
    • Google Cloud Endpoints Eclipseプロジェクトの バックエンドの API  Explorerで クライアントライ クライアント側 作成 実装 動作確認   ブラリの生成 の実装 •  Eclipseのプロジェクト右クリックから生成 •  コマンドラインから生成 sh  appengine-­‐java-­‐sdk-­‐1.7.5/bin/endpoints.sh  get-­‐java-­‐client-­‐lib    jp.vier.sample.endpoints.sample.v1.SampleEndpoint 23
    • Google Cloud Endpoints Eclipseプロジェクトの バックエンドの API  Explorerで クライアントライ クライアント側 作成 実装 動作確認   ブラリの生成 の実装 •  ポイント •  コードが正しくない場合にはクライアントライ ブラリ生成時にエラーが発生する •  エラー内容は「エラー・ログ」(Error Log) ビューに表示される •  Eclipseでよく使う「問題」 (Problems)ビューでは 無いので注意 24
    • Google Cloud Endpoints Eclipseプロジェクトの バックエンドの API  Explorerで クライアントライ クライアント側 作成 実装 動作確認   ブラリの生成 の実装 •  JavaScript 初期化処理(with AngularJS) <script type="text/javascript"> var ENDPOINTS_ROOT = https://[your_app_id].appspot.com/_ah/api; function init() { // EndpointsのAPIを使うための初期化処理 // (第一引数はサーバー側の@APIに定義したAPI名) gapi.client.load(’appData, v1, function() { // angular init angular.bootstrap(document,[ui.bootstrap,my.filter]); }, ENDPOINTS_ROOT); } </script> <script src="https://apis.google.com/js/client.js?onload=init"></script> 25
    • Google Cloud Endpoints Eclipseプロジェクトの バックエンドの API  Explorerで クライアントライ クライアント側 作成 実装 動作確認   ブラリの生成 の実装 •  JavaScript 関数実行(with AngularJS) $scope.getAppData=function() { // API実行 gapi.client.appData.data.get({id:$scope.id}).execute(function(response) { // レスポンスを受け取って処理する $scope.appData = response; $scope.$apply(); }); ・JavaScriptの関数を呼び出すことでサーバーのAPIを実行して結果を取得できる。 ・AngularJSでは値の変更を反映するために「$scope.$apply();」が必要。  (AngularJSで「$http.get」を使った場合と違い、自動で反映されない) 26
    • Google Cloud Endpoints Eclipseプロジェクトの バックエンドの API  Explorerで クライアントライ クライアント側 作成 実装 動作確認   ブラリの生成 の実装 •  JavaScript エラーハンドリング(with AngularJS) $scope.getAppData=function() { // API実行 gapi.client.appData.data.get({id:$scope.id}).execute(function(response,rawResponseJson) { // for local if(response===false){ var rawResponse = JSON.parse(rawResponseJson); // エラーダイアログを表示する $scope.openErrorModal(rawResponse[0].error.message); $scope.$apply(); // for production }else if(response.error && response.error.data && response.error.data.length > 0){ // エラーダイアログを表示する $scope.openErrorModal(response.error.data[0].message); $scope.$apply(); // success ・エラーメッセージとhttpのステータスコードを取得できる。 }else{ ・ローカル環境とProduction環境でエラー時の挙動が異なる。(バグ?) $scope.appData = response; ・rawResponseJsonは本来不要だが、 $scope.$apply();  ローカル環境でエラーハンドリングする際に必要。 } }); } 27
    • Google Cloud Endpoints Eclipseプロジェクトの バックエンドの API  Explorerで クライアントライ クライアント側 作成 実装 動作確認   ブラリの生成 の実装 •  Android メソッド実行 AppData.Builder builder = new AppData.Builder(AndroidHttp.newCompatibleTransport(), new GsonFactory(), null); AppData appDataApi = CloudEndpointUtils.updateBuilder(builder).build(); AppDataV1 response = appDataApi.data().get(id).execute(); ・生成されたクライアント・ライブラリを実行するだけで  サーバー側の処理の返り値を取得できます。 ・通常AsyncTaskの中で実行することになるでしょう。 28
    • Google Cloud Endpoints Eclipseプロジェクトの バックエンドの API  Explorerで クライアントライ クライアント側 作成 実装 動作確認   ブラリの生成 の実装 •  Android エラーハンドリング @Override   protected  AppDataV1  doInBackground(Void...  unused)  {          try  {                  AppData.Builder  builder  =  new  AppData.Builder(AndroidHbp.newCompaRbleTransport(),  new  GsonFactory(),  null);                  AppData  appDataApi  =  CloudEndpointURls.updateBuilder(builder).build();                  AppDataV1  response  =  appDataApi.data().get(id).execute();                  return  response;          }  catch  (final  GoogleJsonResponseExcepRon  e)  {                  handler.post(new  Runnable()  {                          @Override   ・サーバーから返されたエラーは                        public  void  run()  {    GoogleJsonResponseExceptionとしてcatchして                                //  サーバー側で例外インスタンス生成時に渡したメッセージを取得する String  resMessage  =  e.getDetails().getMessage();   エラーメッセージを取得する。                                Toast.makeText(context,  "Error:  "  +  resMessage,  Toast.LENGTH_LONG).show();                                  return;   ・エラーメッセージの他にステータスコードも取得できる。                        }   ・IOExceptionは通信エラーとして処理する。                });                  return  null;          }  catch  (IOExcepRon  e)  {                        //  通信エラーのケース handler.post(new  Runnable()  {                          @Override                          public  void  run()  {                                  Toast.makeText(context,  “通信エラーが発生しました。ネットワーク状態を確認してください。",  Toast.LENGTH_LONG).show();                                  return;                          }                  });                  return  null;          }   } 29
    • Google Cloud Endpoints Eclipseプロジェクトの バックエンドの API  Explorerで クライアントライ クライアント側 作成 実装 動作確認   ブラリの生成 の実装 •  ポイント •  関数やメソッドを実行するだけで、内部的に サーバー側のAPIを実行して返り値を取得 できます。 •  クライアント側の実装方法はGoogleが提供 するAPIの使い方とほとんど同じなので、   困ったときはGoogle APIの使い方をググる   と良いかもしれません。 •  Endpointsの情報に比べると情報がたくさんあり ます。 30
    • Google Cloud Endpoints Eclipseプロジェクトの バックエンドの API  Explorerで クライアントライ クライアント側 作成 実装 動作確認   ブラリの生成 の実装 Tips:Androidの実機からローカルサーバーに接続してテ ストする方法 •  Android側はCloudEndpointUtilsを使う •  「Generate AppEngine Backend」をすると生成される。 •  使い方は 前述の「Android メソッド実行」を参照。 •  CloudEndpointUtils#LOCAL_ANDROID_RUNをtrueにする。 •  サーバー側はデバッグ設定を変更 •  デバッグの構成 -> 引数タブ -> 「プログラムの引数」に 「--address=0.0.0.0 」を追加する。 31
    • Google Cloud Endpoints OAuth2認証 32
    • Google Cloud Endpoints OAuth2: ClientIDの生成 APIs Console -> API Accessで以下のように設定 JavaScript用 Android用 33
    • Google Cloud Endpoints OAuth2: サーバー側の実装例 /** Web用ClientId */private static final String CLIENT_ID_WEB = "10*********09-7ufji**********k2a91.apps.googleusercontent.com";/** Android用ClientId */private static final String CLIENT_ID_ANDROID = "10*********09-o4e8d**********gt2ts3.apps.googleusercontent.com";/** Android用Audience */private static final String AUDIENCE_ANDROID = CLIENT_ID_WEB;@ApiMethod( OAuth2認証を利用する場合はClientIDの定義は必須。 ここに定義したClientID以外で認証して取得したTokenでアクセスした name = "data.put", 場合、引数「user」はnullになる。(認証してないものとして扱われる) path = "data/put", Androidで認証してアクセスする場合のみ「audiences」の指定が必要。 clientIds = {CLIENT_ID_WEB, CLIENT_ID_ANDROID }, audiences = AUDIENCE_ANDROID)public AppDataV2 put(AppDataV2 appDataV2, User user) throws ServiceException { // 認証チェック com.google.appengine.api.users.User型の引数を定 義すると、 if (user == null) { OAuth2認証済みの場合に throw new UnauthorizedException(“ログインが必要です。"); Userクラスにユーザー情報がセットされる。 } // データの登録処理 認証チェックはuserがnullかどうかで判定し、} UnauthorizedExceptionをthrowする。*実際には定数は別のクラスに定義した方が複数バージョンの対応等で使い勝手が良いです。 34
    • Google Cloud Endpoints OAuth2: JavaScriptの実装例 var  mainCtrl  =    funcRon($scope)  {        var  CLIENT_ID  =  10*********09-­‐7uri**********k2a91.apps.googleusercontent.com;      var  SCOPES  =  hbps://www.googleapis.com/auth/userinfo.email’;      //  OAuthライブラリをloadして自動で認証を試みる   ・Web用のClient_IDを使用    gapi.client.load(oauth2,  v2,  funcRon(response)  {   ・scopeは最低限「userinfo.email」が必要                $scope.signin(true,  $scope.userAuthed);      });   ・認証処理の実行    //  OAuth認証関数   ・画面表示時に「可能であれば自動認証」する      $scope.signin=funcRon(mode)  {    際は「immediate:  true」にする。                  gapi.auth.authorize({client_id:  CLIENT_ID,   ・ボタン押下等で明示的に認証する場合は                          scope:  SCOPES,  immediate:  mode,    「immediate:  false」にする。                          response_type:  token  id_token},                            $scope.userAuthed);        };   ・認証処理完了時のcallbackで    //  認証後にユーザー情報を取得するcallback関数        $scope.userAuthed  =  funcRon()  {    ユーザー情報の取得とTokenの設定を行う。                var  request  =  gapi.client.oauth2.userinfo.get().execute(funcRon(response)  {                          if  (!response.code)  {                                  var  token  =  gapi.auth.getToken();   ・サインアウトは「gapi.auth.setToken(null);」でOK。                                  token.access_token  =  token.id_token;                                  gapi.auth.setToken(token);                                                                    //  User情報を取得 $scope.user=response;   ・明示的なSign  in処理の呼び出し部分                                  //  反映させる $scope.$apply();   <a  ng-­‐click="signin(false);">  Sign  In  </a>                          }                  });          }  }     35
    • Google Cloud Endpoints OAuth2: Androidの実装例 (Credentialの管理) private  staRc  final  String  CLIENT_ID  =  "10*********09-­‐7uri**********k2a91.apps.googleusercontent.com";     ・サーバー側でAudienceに指定したClient_IDを指定private  GoogleAccountCredenRal  credenRal;     Credentialの定義@Override  protected  void  onCreate(Bundle  savedInstanceState)  {          super.onCreate(savedInstanceState);          setContentView(R.layout.acRvity_main);   Credentialを生成する。          //  CredenRalを生成する credenRal  =  GoogleAccountCredenRal.usingAudience(this,  "server:client_id:"  +  CLIENT_ID);  }    private  void  setAccountName(String  accountName)  {   認証情報をCredinRalにセットする。          //  CredenRalにアカウント名をセット credenRal.setSelectedAccountName(accountName);  }       36
    • Google Cloud Endpoints OAuth2: Androidの実装例 (アカウント選択) //  「Googleアカウント選択用Picker」を表示する private  void  chooseAccount()  {          startAcRvityForResult(credenRal.newChooseAccountIntent(),  REQUEST_ACCOUNT_PICKER);  }    @Override  protected  void  onAcRvityResult(int  requestCode,  int  resultCode,  Intent  data)  {          super.onAcRvityResult(requestCode,  resultCode,  data);          switch  (requestCode)  {          //  「Googleアカウント選択用Picker」の選択結果を取得する case  REQUEST_ACCOUNT_PICKER:                  if  (data  !=  null  &&  data.getExtras()  !=  null)  {                          Bundle  bundle  =  data.getExtras();                          String  accountName  =  bundle.getString(AccountManager.KEY_ACCOUNT_NAME);                          if  (accountName  !=  null)  {                                  //  CredenRalにアカウント名をセット setAccountName(accountName);                          }                  }                  break;          }  }   37
    • Google Cloud Endpoints OAuth2: Androidの実装例 (クライアントライブラリ実行) AppData.Builder  builder  =  new  AppData.Builder(                AndroidHbp.newCompaRbleTransport(),                new  GsonFactory(),                  credenRal);  AppData  appDataApi  =  CloudEndpointURls.updateBuilder(builder).build();   認証情報を使用してAPIを実行する場合には、 Credentialを引数に渡す。 (認証情報が不要な場合にはnullを渡せばOK) 38
    • Google Cloud Endpoints OAuth2: サーバーに渡せるTokenは二種類ある Id_token access_token 公式サンプルが使用している形式 API  Explorerが使用している形式(*1)  ドキュメントに書かれている形式 ドキュメントに書かれてない形式(*2)  User情報からEmailアドレスと User情報からUserId、Email、NickNameのみ取得できる (*3) NickName、AuthDomainを取得できる 認証したユーザーの権限をサーバー 認証したユーザーの権限をサーバー側で行使できない(たぶん) 側で行使できる(若干強引に)(*4) Token生成に使用したClientIDのチェッ Id_token同様にチェックが行われる。  クが行われる(Token  swap  aback対策) (ただしAPI  Explorerは無条件で許可) *1 認証に関してはドキュメント通りのJS・Android実装とAPI Explorerで挙動が異なります。*2 Endpointsのドキュメントに書かれていない方式なので継続的にサポートされるか不明。*3 id_tokenを使った場合にUserIDを取得できない事に関してはissueが上げられて  Acceptedになっているのでバグとして修正されるかもしれません。*4 Endpointsの機能としてTokenやCredentialを取得する仕組みは無いようです。  HttpServletRequest#getHeaderメソッドでaccess_token文字列を直接取得する必要があります。各クライアント・Tokenタイプによる挙動に関する詳細は「http://goo.gl/44vNj」を参照。 39
    • Google Cloud Endpoints デモ (JavaScript & Android) •  サーバー側API •  一覧取得 •  メッセージ投稿(要認証)•  クライアント •  一覧取得 •  メッセージ投稿 •  認証機能 40
    • Google Cloud Endpoints 参考リンク •  公式ドキュメント •  http://goo.gl/6wp7R•  公式サンプル (tictactoe) •  Android - http://goo.gl/xjX1B •  Backend & JS- http://goo.gl/V8MEV•  API Explorer •  https://developers.google.com/apis-explorer/#s/•  Google APIs Discovery Service •  https://developers.google.com/discovery/?hl=ja•  APIs Console •  https://code.google.com/apis/console/•  Blog @vierjp 「Google Cloud Endpointsを試してみた」 •  http://blog.vier.jp/2013/02/google-cloud-endpoints-12.html 41
    • BigQuery 新機能のデモ •  Small JOINと Big JOIN•  GROUP BYとGROUP EACH BY*デモの内容はブログ( http://goo.gl/jJnuR )の解説と同じです。 42
    • BigQuery 参考リンク •  BigQuery 公式ドキュメント •  https://developers.google.com/bigquery/•  BigQuery Query Reference (JOIN) •  http://goo.gl/LKEZq•  BigQuery Query Reference (GROUP BY) •  http://goo.gl/EI2aK•  Google Developers Blog (BigQuery gets big new features to make data analysis even easier) •  http://goo.gl/Unwmq•  Blog @vierjp 「BigQueryの新機能 (2013/03/15)」 •  http://blog.vier.jp/2013/03/bigquery-20130315.html 43
    • Google Cloud Endpoints & BigQuery ご清聴ありがとうございました 時間の都合で扱えなかった細かい内容はブログで! http://blog.vier.jp/ 44