まだプログラマーですが何か?

プログラマーネタとアスリートネタ中心。たまに作成したウェブサービス関連の話も http://twitter.com/dotnsf

タグ:json

IBM Bluemix を通じて提供されているコグニティブサービス(認識型人工知能)API の1つに Tradeoff Analytics があります:
2015051800


この API を理解するにはデモサイトを参照していただくのがいいと思います:
http://tradeoff-analytics-demo.mybluemix.net/

このデモサイトでは「一覧の中で、自分にあったスマホはどれか?」という命題を、その人が重要視するスペックポイントを明確にした上で候補を上げていく、というものです。

スマホはメモリは多い方がいいし、バッテリーは多い方がいいけど、そうすると重量が重くなります。でも重量は気にする人もいればいない人もいます。また価格は安い方がいいに決まっていますが、メモリやバッテリー、重量などの要素と比べて重要度が高いのか低いのか、は人によって異なってきます。 全てを満たすパーフェクトなスマホはそうそう出てこないでしょうから、結局はどの要素を重要視するかでトレードオフを考えることになると思いますが、どの要素を重要視した場合はどのような結果になるか、を判断してくれる、そんな API です。

例えば上記デモサイトを開くと、デフォルトでは以下の様な表が表示されます:
2015051801


一番上の列がヘッダで、2行目からがスマホの候補リストになっています。表の3列目以降がスペックになっていて、3列目は価格(小さい方がいい)、4列目はRAMメモリ量(多い方がいい)、5列目はスクリーンサイズ(意見が別れるところですが、ここでは大きい方がいい)、6列目はカメラの画素数(多い方がいい)、7列目はメモリ量(多い方がいい)、8列目はバッテリー容量(多い方がいい)、そして9列目は重量(少ない方がいい)となっています。このうちデフォルト状態では価格、スクリーンサイズ、重量の色が緑になっていて、今はこの3点を重要視する人にとってのトレードオフを解析する指定になっています。

もしもこれら以外の点を重要視したい場合は表右下の "View/Edit JSON" と書かれた箇所をクリックして JSON の内容を変更します。例えば「スクリーンサイズは気にしないけど、バッテリー容量は重要!」という場合は以下のように値を変更します。 まずスクリーンサイズは今回意識しなくていいので、JSON 内の columns の中で "key" 値が "screen_size" になっている項目の "is_objective" 値を true から false に変更します。この "is_objective" の値が true のものはトレードオフの考慮に含めて、false のものは含めない、という指定です。なお "goal" 値が "MAX" のものは「(メモリ量など)大きい方がいい」という値、"MIN" のものは「(価格など)小さい方がいい」という値だという指定です:
{
  "key": "screen_size",
  "full_name": "Screen size (inch)",
  "type": "NUMERIC",
  "is_objective": false,
  "goal": "MAX"
},

続いてバッテリー容量はトレードオフに新たに含めたいので、同様にして "key" 値が "battery" になっている項目の "is_objective" 値を false から true に変更します:
{
  "key": "battery",
  "full_name": "Battery (mAh)",
  "type": "NUMERIC",
  "is_objective": true,
  "goal": "MAX"
},

この状態で編集エリア右下の "Back to table" をクリックすると、価格とバッテリー容量と重量の3点が重要視指定された状態の表が表示されるはずです。なお、これら以外でも JSON を変更することで候補スマホの名称や各数値を変更することもできます。全て JSON フォーマットで指定されていることを確認しておいてください:
2015051802


重要視する項目が決まったら、画面右下の "Analyze Sample Data" と書かれたボタンをクリックして、トレードオフを計算します:
2015051803


すると画面下に以下のようなグラフが表示されて、指定した3項目でのトレードオフを考えた結果が表示されます。各スマホアイテムがそれぞれの要素を意識した時にどの位置にあるのか、ということが視覚化されています:
2015051804


例えば、ここでバッテリー項目の下限のスライダーを 1000 から 1500 近くまで移動させると、「バッテリー容量が指定値(1500)以下のものは考慮しない」という指定をしたことになり、画面上部付近にあったいくつかのバッテリー容量の少ないスマホが画面から消えます。これで更に絞込みやすくなります:
2015051805


・・・と、なんとなく「トレードオフ解析」の意味がお分かりいただけたでしょうか? IBM Bluemix で用意されているのは、このような解析を行うための(与えられた条件から、上記の結果グラフを書くための)API が用意されている、という点が特徴です。つまり上記デモサイトのようなことを皆さんの作るアプリケーションの中でも実現できるようになる、ということです。

実際にこの API を利用するには、IBM Bluemix で上記の Tradeoff Analytics サービスをランタイムアプリケーションにバインドして資格情報を確認し、利用のための username と password を取得しておく必要があります
2015051801


ここまで準備できれば API そのものは単純です。取得した username と password を使って Basic 認証を行い、https://gateway.watsonplatform.net/tradeoff-analytics-beta/api/v1/dilemmas に対して、解析させたい JSON(上記の Edit JSON をクリックして編集したもの)をポストするだけです。

成功すると、以下の様な JSON が結果として返ってきます:
{
  "problem": {
    "columns" : [ {
      "key" : "price",
      "format" : "",
        :
        (ポストした JSON の内容)
        :
  },
  "resolution" : {
    "solutions" : [ {
      :
      :
    } ],
    "map" : [ {
      "nodes" : [ {
        "coordinates" : { "x":0.0, "y":0.0 },
        "solution_refs" : []
      }, {
        "coordinates" : { "x":1.0, "y":0.0 },
        "solution_refs" : []
      }, {
        "coordinates" : { "x":2.0, "y":0.0 },
        "solution_refs" : []
      }, {
        "coordinates" : { "x":3.0, "y":0.0 },
        "solution_refs" : []
      }, {
        "coordinates" : { "x":4.0, "y":0.0 },
        "solution_refs" : []
      }, {
        "coordinates" : { "x":5.0, "y":0.0 },
        "solution_refs" : []
      }, {
        "coordinates" : { "x":6.0, "y":0.0 },
        "solution_refs" : [ "5" ]
      }, 
        :
        :
      } ],
      "anchors" : [ {
        "name" : "price",
        "position" : { "x":0.0, "y":0.0 }
      }, {
        "name" : "battery",
        "position" : { "x":4.5, "y":7.8 }
      }, {
        "name" : "weight",
        "position" : { "x":9.0, "y":0.0 }
      } ],
        :
        :
    }
  }
}

結果の JSON の細かい内容は以下のリファレンスを参照していただきたいのですが、大きく3つの箇所を参照することになります。 1つ目は "problem" で、この中にポストした JSON がそのまま記述されているはずです。つまり「この問題に対する実行結果である」ことを示しています。

2つ目は "resolutions" の中の "map" で、ここに散布図を書いた時の各点の座標(x,y)が示されており、またその座標位置に相当するアイテムがあった場合は "solutions_refs" という配列値で示されます。例えば上の例ですと ( 6.0, 0.0 ) の位置に "key" 値が "5" に相当するアイテムがある、ということになります。

最後の3つ目は "resolutions" の中の "anchors" で、これが指定した各トレードオフ要素(この例では価格とバッテリー容量と重量)が散布図上のどの位置にあるかを示しています。


後はこの結果を受け取った側でどのように見せるか、という問題になります。チャート描画の API を使ってもいいし、Canvas を使って自分で記述してもいいと思います。ここから先は開発者やデザイナーの腕の見せ所と言えます。そういう意味ではここのデモサイトはなかなか良くできてますよね。


というわけで、これまでにこのブログで紹介してきたコグニティブサービスとは少し(特に実行方法の面で)毛色が違うサービスと言えます。API 実行時に指定フォーマットの JSON を作る必要があるのが少し面倒ですが、トレードオフを意識する要素と、それらの値は大きい方が嬉しいのか小さい方が嬉しいのかの情報、そしてアイテムの一覧を JSON にしてポストすれば結果が返ってくる、というものです。REST API そのものはシンプルなのでエクセルのような表計算からも実行できると思っています(エクセルだと逆に結果の視覚化が難しいかも・・)。


なお、ここで紹介した Watson Tradeoff Analytics API について、詳しくは API リファレンスを参照してください:
http://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/apis/#!/tradeoff-analytics
 

IBM DB2 V10.5 ではテクノロジープレビューという正式サポート前の扱いですが、NoSQL 機能が使えるようになっています。

これは MongoDB のような JSON オブジェクトストア機能であり、実際に MongoDB のコマンドラインクライアントからも利用することができます。

このテクノロジープレビュー機能を有効にして、実際に使ってみるまでの手順を紹介します。なお環境は CentOS 6(64bit) 版を前提とします。


まず IBM DB2 V10.5 を導入します。DB2 は無償版の Express-C エディションが提供されているのでそれを使います。詳しい手順はこちらのエントリを参照ください(エントリはバージョン10.1での説明ですが、2015年1月5日現在、同じ手順で最新のバージョン10.5がダウンロード&導入できます):
DB2 Express-C (10.1) を CentOS にインストール&セットアップする


併せて MongoDB を導入します。詳しい手順はこちらを参照ください(この手順では MongoDB サーバーも導入されますが、今回はクライアントのみ使います):
mongoDB を CentOS 上にインストールする


最後に DB2 の NoSQL 機能を有効化する手順の中で JRE が必要になるため、Java 実行環境を導入します:
# yum install java-1.7.0-openjdk


ここまでの準備ができたら実際に DB2 の NoSQL 機能のセットアップを行います。システム上で db2inst1 ユーザーに切り替えて、NoSQL 用のデータベース jsondb をコードセット UTF-8、テリトリー jp で作成します(異なる内容で作成する場合はコマンドの赤字部分を該当内容に合わせて変更してください):
# su - db2inst1
$ db2 create database jsondb automatic storage yes using codeset utf-8 territory jp collate using system

しばらく待つと NoSQL データベース jsondb が作成されます。プロンプトが戻ったら続けて DB2 のポートを開きます。そして DB2 を再起動(ストップ&スタート)して、この内容を反映させます:
$ db2set DB2COMM=TCPIP
$ db2 update dbm cfg using svcename 50000
$ db2stop
$ db2start

そして db2inst1 ユーザーの ~/.bashrc を開いて編集し、環境変数の設定を行います:
$ vi ~/.bashrc
  :
  :
(最後に以下を追加して保存)
export JAVA_HOME=/usr/lib/jvm/jre-1.7.0-openjdk.x86_64
export PATH=$PATH:/opt/ibm/db2/V10.5/json/bin
export CLASSPATH=$CLASSPATH:/opt/ibm/db2/V10.5/json/lib/nosqljson.jar:/opt/ibm/db2/V10.5/json/lib/mongo-2.8.0.jar:/opt/ibm/db2/V10.5/json/lib/js.jar:/opt/ibm/db2/V10.5/json/lib/db2NoSQLWireListener.jar

上記で作成した jsondb データベースは初期状態では無効になっているので、コマンドラインから有効になるよう指定します。改めて db2inst1 ユーザーでログインし(或いは上記の ~/.bashrc の変更を反映し)、以下のコマンドを実行します:
# su - db2inst1
$ cd /opt/ibm/db2/V10.5/json/bin
$ ./db2nosql.sh -user db2inst1 -hostName localhost -port 50000 -db jsondb -setup enable -password (db2inst1ユーザーのパスワード)

最後に通信リスナーを MongoDB と同じ 27017 番ポートで起動します(db2inst1 ユーザーで、/opt/ibm/db2/V10.5/json/bin ディレクトリ上で実行する必要があります):
$ cd /opt/ibm/db2/V10.5/json/bin
$ ./wplistener.sh -start -mongoPort 27017 -userid db2inst1 -password (db2inst1ユーザーのパスワード) -dbName jsondb -logPath /tmp

   :
--- The wire listener is being started ---
Starting the channel listener on port 27017

上記のように、画面に "Starting the chennel listener on port 27017" と表示されれば DB2 の NoSQL データベース機能の起動に成功しています。


最後に動作確認の意味で、この DB2 上で動いている NoSQL データベース jsondb に、MongoDB クライアントから接続してみましょう。同じシステム上の別端末を開いて、mongo コマンド(MongoDB クライアント)を実行してみます(青字はシステムからの出力結果です):
# mongo
MongoDB shell version: 2.6.6
connecting to: test
>

エラーが表示されていなければ接続できたことになります。続けて jsondb データベースに接続して、myfirstcollection コレクションに "_id" = 100 の JSON 文書を作成/更新/検索してみます:
> use jsondb (DB変更)
switched to db jsondb
> db.myfirstcollection.insert( { "_id":100, "name":"K.Kimura" } ) (文書作成)
Cannot use commands write mode, degrading to compatibility mode
WriteResult({ "nInserted" : 1 })
> db.myfirstcollection.findOne() (検索)
{ "_id" : 100, "name" : "K.Kimura" } (成功)
> db.myfirstcollection.update( { "_id":100 }, {"name":"Kei KIMURA" } ) (更新)
WriteResult({ "nMatched" : 1, "nUpserted" : 0 }) (成功)
> db.myfirstcollection.findOne() (再検索)
{ "_id" : 100, "name" : "Kei KIMURA" } (成功)
  :
  :
> quit()
#

MongoDB クライアントからの一通りのコマンドは全て成功しているようです。


mongo の基本的なコマンドに関しては全て動いているようですが、どの程度の互換性があるのか/ないのか、MongoDB のライブラリが使えるのか/使えないのか、まだちょっとわかりません。 でもこれが使えるようであれば、PHP から MongoDB ライブラリを経由して DB2 にアクセスする、といった、これまでできなかったような使い方も広がってくると思います。この機能が正式サポートされるのが楽しみです。




(参考)
http://www.ibm.com/developerworks/jp/data/library/techarticle/dm-1306nosqlforjson4/
 

今年(2014年)の10月31日より、オープンデータ高度化の一環で総務省統計局より政府統計データの多くが Web API にて公開されました:
API機能で利用できる統計データの拡充 -統計におけるオープンデータの高度化- (PDF)

この公開された政府統計データ(eStat)を使ったサンプルを紹介します。
top_header_logo



まず、この政府統計データを使う上での利用者登録と、アプリケーション登録が必要です。利用者登録は以下のページから行います:
利用登録・ログイン

メールアドレスやパスワードを登録し、最終的にアクティベートまで行い、利用登録が完了すると上記ページからログインできるようになります。

ログイン後にアプリケーション登録を行います。「アプリケーションIDの取得」をクリックして、アプリケーションの名称、URL 、概要を入力し、「発行」ボタンをクリックすると appId と書かれた箇所にアプリケーション ID が表示されます。これは後から使う情報になるのでメモするなどしておきます(以下、appId を XXXXXXXXXX として説明を続けます):
2014121501


なお、1つの利用IDで最大3つまでのアプリケーションが登録できます。ウェブ上に公開されているアプリケーションから利用する場合はその URL を指定する必要があります。公開されていないアプリや、テスト目的で利用したい場合はURLに http://localhost/ を指定すればいいようです。


アプリケーションの登録が完了し、appId が取得できたら早速 API を利用してみましょう。まずはどのような統計データが公開されているのか、その一覧を取り出してみます。

データリストを取得するには、以下の URL に GET アクセスします:
http://statdb.nstac.go.jp/api/1.0b/app/getStatsList?appId=XXXXXXXXXX&statsCode=ZZZZ

getStatsList では URL パラメータが2つ指定されています。appId には上記で取得したアプリケーション ID を、そして statsCode には政府統計コードを指定します。例えば平成22年に実施・更新された国勢調査のデータを取得するのであれば、政府統計コードは 00200521 になるので、こんな感じです:
http://statdb.nstac.go.jp/api/1.0b/app/getStatsList?appId=XXXXXXXXXX&statsCode=00200521
(XXXXXXXXXX = 取得したアプリケーションID)

結果は以下の様な XML フォーマットで取得できます:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<GET_STATS_LIST xsi:noNamespaceSchemaLocation="http://statdb.nstac.go.jp/api/1.0b/schema/GetStatsList.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <RESULT>
  <STATUS>0</STATUS>
  <ERROR_MSG>正常に終了しました。</ERROR_MSG>
  <DATE>2014-12-15T15:15:36.690+09:00</DATE>
 </RESULT>
 <PARAMETER>
  <LANG>J</LANG>
  <STATS_CODE>00200521</STATS_CODE>
 </PARAMETER>
 <DATALIST_INF>
  <NUMBER>4180</NUMBER>
  <LIST_INF id="0000030001">
   <STAT_NAME code="00200521">国勢調査</STAT_NAME>
   <GOV_ORG code="00200">総務省</GOV_ORG>
   <STATISTICS_NAME>昭和55年国勢調査 第1次基本集計 全国編</STATISTICS_NAME>
   <TITLE no="00101">男女の別(性別)(3),年齢5歳階級(23),人口 全国・市部・郡部・都道府県(47),全域・人口集中地区の別</TITLE>
   <CYCLE>-</CYCLE>
   <SURVEY_DATE>198010</SURVEY_DATE>
   <OPEN_DATE>2007-10-05</OPEN_DATE>
   <SMALL_AREA>0</SMALL_AREA>
  </LIST_INF>
  <LIST_INF id="0000030002">
   <STAT_NAME code="00200521">国勢調査</STAT_NAME>
   <GOV_ORG code="00200">総務省</GOV_ORG>
   <STATISTICS_NAME>昭和55年国勢調査 第1次基本集計 全国編</STATISTICS_NAME>
   <TITLE no="00102">男女の別(性別)(3),年齢各歳階級(103),人口 全国・市部・郡部・都道府県(47),全域・人口集中地区の別</TITLE>
   <CYCLE>-</CYCLE>
   <SURVEY_DATE>198010</SURVEY_DATE>
   <OPEN_DATE>2007-10-05</OPEN_DATE>
   <SMALL_AREA>0</SMALL_AREA>
  </LIST_INF>
  <LIST_INF id="0000030003">
    :
  </LIST_INF>
    :
    :
 </DATALIST_INF>
</GET_STATS_LIST>

<DATALIST_INF> の中に複数の <LIST_INF> 要素があり、それら1つ1つが異なる統計データを示しています。また個々の統計データにはデータの説明文なども含まれており、 <LIST_INF id="YYYYYYYYYY"> の YYYYYYYYYY 部分が ID として区別されています。これでどのような統計データがあるか、の一覧が管理されています。


また、統計データの種類を1つ指定して、実際の統計データを取得するには getStatsData を使います:
http://statdb.nstac.go.jp/api/1.0b/app/getStatsData?appId=XXXXXXXXXX&statsDataId=YYYYYYYYYY

パラメータの appId には getStatsList の時と同様にアプリケーション ID を、また statsDataId には getStatsList で取得したデータID(上記の赤字で示されている部分)を指定します。 上記例の一番上にある「昭和55年国勢調査の年齢5歳階級別の人口データ」であれば 0000030001 なので、以下の様な URL になります:
http://statdb.nstac.go.jp/api/1.0b/app/getStatsData?appId=XXXXXXXXXX&statsDataId=0000030001

そして、この結果は以下の様な XML フォーマットで取得できます:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<GET_STATS_DATA xsi:noNamespaceSchemaLocation="http://statdb.nstac.go.jp/api/1.0b/schema/GetStatsData.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <RESULT>
  <STATUS>0</STATUS>
  <ERROR_MSG>正常に終了しました。</ERROR_MSG>
  <DATE>2014-12-15T15:15:38.380+09:00</DATE>
 </RESULT>
 <PARAMETER>
  <LANG>J</LANG>
  <STATS_DATA_ID>0000030001</STATS_DATA_ID>
  <DATA_FORMAT>X</DATA_FORMAT>
  <START_POSITION>1</START_POSITION>
  <METAGET_FLG>Y</METAGET_FLG>
 </PARAMETER>
 <STATISTICAL_DATA>
  <TABLE_INF id="0000030001">
   <STAT_NAME code="00200521">国勢調査</STAT_NAME>
   <GOV_ORG code="00200">総務省</GOV_ORG>
   <STATISTICS_NAME>昭和55年国勢調査 第1次基本集計 全国編</STATISTICS_NAME>
   <TITLE no="00101">男女の別(性別)(3),年齢5歳階級(23),人口 全国・市部・郡部・都道府県(47),全域・人口集中地区の別</TITLE>
   <SURVEY_DATE>198010</SURVEY_DATE>
   <TOTAL_NUMBER>3651</TOTAL_NUMBER>
   <FROM_NUMBER>1</FROM_NUMBER>
   <TO_NUMBER>3651</TO_NUMBER>
  </TABLE_INF>
  <CLASS_INF>
   <CLASS_OBJ id="cat01" name="全域・集中の別030002">
   <CLASS code="00700" name="全域" level="1"/>
   <CLASS code="00701" name="人口集中地区" level="1"/>
  </CLASS_OBJ>
  <CLASS_OBJ id="cat02" name="男女A030001">
   <CLASS code="000" name="男女総数" level="1"/>
   <CLASS code="001" name="男" level="1"/>
   <CLASS code="002" name="女" level="1"/>
  </CLASS_OBJ>
  <CLASS_OBJ id="cat03" name="年齢5歳階級A030002">
   <CLASS code="000" name="総数" level="1" unit="人"/>
   <CLASS code="001" name="0-4歳" level="1" unit="人"/>
   <CLASS code="002" name="5-9歳" level="1" unit="人"/>
   <CLASS code="003" name="10-14歳" level="1" unit="人"/>
     :
  </CLASS_OBJ>
  <CLASS_OBJ id="area" name="全国都道府県030001">
   <CLASS code="00000" name="全国" level="1"/>
   <CLASS code="00001" name="全国市部" level="1"/>
   <CLASS code="00002" name="全国郡部" level="1"/>
   <CLASS code="01000" name="北海道" level="1"/>
   <CLASS code="02000" name="青森県" level="1"/>
   <CLASS code="03000" name="岩手県" level="1"/>
     :
  </CLASS_OBJ>

  <DATA_INF>
   <NOTE char="***">当該数値がないもの</NOTE>
   <NOTE char="-">当該数値がないもの</NOTE>
   <VALUE cat01="00700" cat02="000" cat03="000" area="00000" time="1980000000" unit="人">117060396</VALUE>
   <VALUE cat01="00700" cat02="000" cat03="000" area="00001" time="1980000000" unit="人">89187409</VALUE>
   <VALUE cat01="00700" cat02="000" cat03="000" area="00002" time="1980000000" unit="人">27872987</VALUE>
   <VALUE cat01="00700" cat02="000" cat03="000" area="01000" time="1980000000" unit="人">5575989</VALUE>
   <VALUE cat01="00700" cat02="000" cat03="000" area="02000" time="1980000000" unit="人">1523907</VALUE>
   <VALUE cat01="00700" cat02="000" cat03="000" area="03000" time="1980000000" unit="人">1421927</VALUE>
   <VALUE cat01="00700" cat02="000" cat03="000" area="04000" time="1980000000" unit="人">2082320</VALUE>
   <VALUE cat01="00700" cat02="000" cat03="000" area="05000" time="1980000000" unit="人">1256745</VALUE>
   <VALUE cat01="00700" cat02="000" cat03="000" area="06000" time="1980000000" unit="人">1251917</VALUE>
     :
  </DATA_INF>
 </STATISTICAL_DATA>
</GET_STATS_DATA>

この結果(<STATISTICAL_DATA>)は以下のように読み解けます。

まず、<CLASS_INF> を見ることで、データは4つのカテゴリ分類がされています。まず cat01 が「全域(00700)か、人口集中地区(00701)か」を示しています。

次に cat02 は男女別分類をしています。男女総数のデータ(000)なのか、男性のみのデータ(001)なのか、それとも女性のみのデータ(002)なのか、という分類のようです。

そして cat03 は年齢を5歳区切りにした分類です。全年代(000)、0~4歳(001)、5~9歳(002)、・・といった具合で分類されていることが分かります。

最後に area が都道府県別分類をしていることが分かります。全国(00000)、全国市部(00001)、全国郡部(00002)、北海道(01000)、青森(02000)、・・・といった具合のようです。


続いて <DATA_INF> 内の <VALUE> 部分が実際の数値データになっています。例えば先頭にあるこのデータ:
<VALUE cat01="00700" cat02="000" cat03="000" area="00000" time="1980000000" unit="人">117060396</VALUE>
これは cat01=00700, cat02=000, cat03=000, area=0000 という属性が付与されているので、エリアは全域、男女総数、全年代の全国での人口総数を意味していて、その数値が 117060396 (人)である、ということが分かります。

したがって、例えば年代毎の全国の人口分布を調べたいのであれば、cat01=00700, cat02=000, area=00000 で固定して、cat03 が 001 以上のものをフィルタリングして調べればよい、ということになりますね。 


なお、Web API の app と getStats***** の間に json を入れると、出力結果が XML ではなく JSON フォーマットになります。JSON で必要な場合はこちらを使ってください:
http://statdb.nstac.go.jp/api/1.0b/app/json/getStatsList?appId=XXXXXXXXXX&statsCode=00200521
http://statdb.nstac.go.jp/api/1.0b/app/json/getStatsData?appId=XXXXXXXXXX&statsDataId=0000030001






 

IBM Bluemix の "Cloundant" サービスを試しに使ってみました。


まず Cloudant について説明します。Cloudant は JSON ドキュメントデータベースである Apache CouchDB をベースとする DBaaS サービスを提供しているマサチューセッツ州の企業です(2014年3月にIBM による買収が発表されました)。

このサービスが Could Foundry ベースの PaaS である IBM Bluemix のサービスの1つとして提供されている、ということになります。利用する側の観点で言えば「IBM Bluemix 内で使える Apache CouchDB」ということになります。価格等は後述します。


では実際に IBM Bluemix から Cloudant サービスを使う手順を紹介します。IBM Bluemix にログインし、ダッシュボードなどの画面から "ADD SERVICE" をクリックします:
2014081601


サービス一覧の "Data Management" カテゴリの中に "Cloudant NoSQL DB" を見つけることができます。これをクリックします:
2014081602


"Cloundant NoSQL DB" の説明が表示されます。この時点で特定のアプリケーションサーバーに紐付けるのであれば APP からアプリケーションを選択します(試しに使うだけなら特定のアプリケーションへの紐付けは不要です)。そして "CREATE" ボタンをクリックすると Cloudant サービスが生成されます:
2014081603


ちなみに、上記画面の下の方までスクロールするとサービス価格についての説明があります。データ1GBあたり 105円(1ドル?)ですが、2GB までは無料枠内で使えるようです。加えて API の実行回数についても無料枠と有料枠が設定されているようです。今回は無料枠内でしか使わないつもりです:
2014081604


Cloudant サービスが生成されるとダッシュボード内にこのようなパネルが追加されているはずです。この "Show Credentials" と書かれた箇所をクリックすると、Cloudant サーバーへアクセスするための Credentials 情報が表示されます(下図参照):
2014081605


Credentials 情報を確認している画面です。username や password などもありますが、とりあえずすぐ使うので "url" をメモしておきましょう。そしてサービス名(下図だと "Cloudant NoSQL DB-9c")が書かれた箇所をクリックしてサーバーの情報を表示します:
2014081606


Cloudant サービスについても説明が表示されている画面です。この右上に "LAUNCH" と書かれたボタンがあり、ここをクリックしてサーバーコンソールに接続します:
2014081607


別ウィンドウが起動して、Clondant のサーバーコンソールが表示されている画面です。ここでデータベースや複製、アカウントなどの情報を参照したり、実際にドキュメントを読み書きできます。画面ではデータベースタブが選択されていますが、まだデータベースを作成していないので "Add database" ボタンをクリックして最初のデータベースを作成しておきます:
2014081608


データベース名を指定します。ここでは "dotnsfdb" と指定しています:
2014081608a


"dotnsfdb" が作成されたので、Database タブ内の画面が変わりました(まだデータはありません)。画面内の "Create your first document" ボタンをクリックして最初のドキュメントを作成しておきます:
2014081609


中身はこんな感じにしました。 "value" キーに "こんにちは、Cloudant" という日本語の値を追加して、"Save" ボタンをクリックします:
2014081611


保存されました。"Return _all_docs" ボタンで一覧画面に戻ります:
2014081612


dotnsfdb の一覧画面に戻りました。先程作成したドキュメントが表示されています。"_id" の値(この例では"c82b7fb996a83c0bdaead3f75bd44a34")を確認しておきます:
2014081613


このドキュメントを API 経由で呼び出してみます。Credentials 情報から取得した URL を使って、以下の URL にアクセスします:
 (https で始まる "url" の値)/(作成したデータベース名)/(_id の値)

"url" の値にはユーザー名とパスワードも含まれているはずなので、後はデータベース名と _id 値を指定して GET すれば、いま作成したドキュメントの値が取得できるはずです:
2014081615


当たり前ですが、ちゃんと CouchDB の API で目的のドキュメントの情報が取得できました。日本語情報も問題なさそうです。





 

BlueMix でアプリケーションを作ると、データベースなどのサービス環境に接続するための情報を VCAP_SERVICES という変数から取得する必要があります。アプリケーションを Java で開発する場合に、これを具体的にどうやって実現するか、というサンプルを紹介します。


まず、これは Java で開発する場合だけでなく、全ての言語で言えることですが、BlueMix のアプリケーションサーバーにバインドされたサービスの情報は VCAP_SERVICES という環境変数から取得することになります。例えば MySQL サービスとバインドしていると、VCAP_SERVICES 変数には以下のような内容の JSON 文字列が追加されます:
"mysql-5.5": [
      {
         "name": "mysql-scsrh",
         "label": "mysql-5.5",
         "plan": "100",
         "credentials": {
            "name": "(データベース名)",
            "hostname": "XX.XXX.XX.XXX",
            "host": "XX.XXX.XX.XXX",
            "port": 3307,
            "user": "(接続ユーザー名)",
            "username": "(接続ユーザー名)",
            "password": "(接続パスワード)",
            "uri": "mysql://(接続ユーザ名):(接続パスワード)@XX.XXX.XX.XXX:3307/(データベース名)"
         }
      }
   ]
ここから接続に必要な値を取り出して接続することになります。Java 言語で JDBC を使うのであれば、赤字に相当する部分を取り出して、以下の様な処理を実行することでコネクションを取得することができます(別途 MySQL 用の JDBC ドライバを用意しておく必要があります):
try{
  Class.forName( "com.mysql.jdbc.Driver" );
  Connection conn = DriverManager.getConnection( "jdbc:" + "mysql://XX.XXX.XX.XXX:3307/(データベース名)", "(接続ユーザ名)", "(接続パスワード)" );
    :
}catch( Exception e ){
  e.printStackTrace();
}
MySQL に限らず DB2 や MongoDB、Twilio などでも同様です。接続情報が必要かどうかはともかくとして、バインドされたサービスに関する設定情報は VCAP_SERVICES 環境変数の中に JSON 形式で格納されるので、そこから必要な情報を取り出して利用する、という流れになります。


問題は Java で JSON を扱うのが意外と面倒、ということです。JSON は JavaScript 用のオブジェクト形式ですが、Java と JavaScript の親和性がいいとは思えないくらいに扱いが難しいのでした。

とりあえず、サンプルとしてシンプルな JSON ライブラリである JSON simple を使って実装してみます:
jsonsimple

json-simple - A simple java toolkit for JSON
 
これをダウンロードして jar をプロジェクトにインポートした上で、こんな感じのコードを実装することになります:
import org.json.simple.*;
import org.json.simple.parse.*;
import java.sql.*;


:
:
Connection conn = null;
String vcap = System.getenv( "VCAP_SERVICES" );
if( vcap != null ){
//. 環境変数 VCAP_SERVICES をデコード JSONParser parser = new JSONParser(); Object obj = parser.parse( vcap ); JSONObject json = ( JSONObject )obj;
//. mysql5-5 の credentials 以下のみを取り出す
JSONObject credentials = ( JSONObject )( ( JSONObject )( ( JSONArray )json.get( "mysql-5.5" ) ).get( 0 ) ).get( "credentials" );
//. 上記赤字部分の情報を取り出す
String name = ( String )credentials.get( "name" );
String hostname = ( String )credentials.get( "hostname" );
Integer port = ( Integer )credentials.get( "port" );
String username = ( String )credentials.get( "username" );
String password = ( String )credentials.get( "password" );

//. コネクション取得
try{
Class.forName( "com.mysql.jdbc.Driver" );
conn = DriverManager.getConnection( "jdbc:mysql://" + hostname + ":" + port + "/" + name, username, password );
}catch( Exception e ){
e.printStackTrace();
}
}
:

でもまだちと面倒だよなあ・・・ もう少し可読性よく書きたいんだけど、Java だと JSON は本当に厄介です。


 

このページのトップヘ