Cloudantに格納したセンサーデータを利用する

センサーデータにタイムスタンプを付けてCloudantに保管する流れを、[Node-REDを使ってセンサーデータをCloudantに格納する](http://qiita.com/asmanabu/items/809e1276f95e76b989a3)に書きました。
今回は、Cloudantに保管したデータを利用する方法について書きます。

Node-REDを使ってHTTP GETリクエストを受け付けるフローを作成し、この中でCloudantからセンサーデータを取得するようにします。

## 前提
[Node-REDを使ってセンサーデータをCloudantに格納する](http://qiita.com/asmanabu/items/809e1276f95e76b989a3)のフローをBluemix上のNode-REDにデプロイ済みであることとします。

## 作業の流れ
1. CloudantにSearchIndexを作成する
2. Node-REDを使って、HTTP GETリクエストを受け付けるフローを作成する
3. 動作確認

## 1. CloudantにSearchIndexを作成する
Cloudantには、以下の形式でデータが保管されています。Cloudant保管時に任意に付けられる*_id*がキーとなっています。
今回は、タイムスタンプで検索ができるように*timestamp*をキーとするCloudantの[Search Index](https://cloudant.com/for-developers/search/)を作成します。Search Indexを利用することで、Luceneの書式で検索できるようになります。

```
{
  "_id": "07f647f960d8f2cba14221f96646df60",
  "_rev": "1-26ae484039d6ad18c39f1ce0117c6634",
  "timestamp": "2015-04-23 07:52:21",
  "temp": 15,
  "humidity": 76,
  "objectTemp": 24
}
```

Cloudantの管理コンソールでデータベース*sensordata*を選択した状態で、**All Design Docs**の右にある＋ボタンをクリックします。続いて**New Search Index**をクリックします。
![nodered-cloudant12.jpg](https://qiita-image-store.s3.amazonaws.com/0/73397/f55eee09-20fd-df76-4bba-bb54807cbe3b.jpeg)


**Save to Design Document**の**_design/**の後ろに*Index*、**Index name**に*IndexByTimestamp*を入力します。**Search index function**には、以下を入力します。これにより、Cloudantに格納したデータの中の*timestamp*要素をキーとしたインデックスが生成されます。

```
function(doc){
 index("timestamp", doc.timestamp, { "store": true });
}
```

**Type**として*Keyword*を選択し、最後に**Save & Build Index**をクリックします。これでSearch Indexが完成しました。

入力例は以下のとおりです。
![nodered-cloudant13.jpg](https://qiita-image-store.s3.amazonaws.com/0/73397/bc72960d-3f24-3911-b0a9-259db8763d98.jpeg)

## 2. Node-REDを使って、HTTP GETリクエストを受け付けるフローを作成する

Node-REDでは、HTTPリクエストを受け付けるノードが用意されています。これを利用して、ブラウザやプログラムからHTTP GETリクエストを受け付けるフローを作成します。

GETリクエストのクエリーパラメーターは以下のとおりとします。

| パラメータ名 | 用途 | 書式 |
| :--: | :-- | :-- |
| start | センサーデータのタイムスタンプの検索開始日時 | yyyy-mm-ddThh:mm:ssZ |
| end| センサーデータのタイムスタンプの検索終了日時 | yyyy-mm-ddThh:mm:ssZ |

リクエストの例です。
```
http://sample.mybluemix.net/sensordata?start=2015-04-22T19:40:00Z&end=2015-04-22T19:40:00Z
```

それではフローを作成します。Node-REDのフローエディターを使って、以下のフローを作成します。
![nodered-cloudant14.jpg](https://qiita-image-store.s3.amazonaws.com/0/73397/d567684c-2728-2fda-4c0d-50f2f52a16a7.jpeg)

以下の5つのノードを利用しています。

| ノード |  | 用途 |
|:--|:-:|:--|
| httpノード | ![nodered-http.jpg](https://qiita-image-store.s3.amazonaws.com/0/73397/25e565b7-5014-abcc-71f5-b91f8f59596b.jpeg) | HTTPリクエストの受付 |
| functionノード | ![nodered-function.jpg](https://qiita-image-store.s3.amazonaws.com/0/73397/b1d5e723-95bc-af84-b0de-e18ed6f2c25b.jpeg) | リクエストパラメータからCloudant検索用文字列の生成 |
| Cloudantノード | ![nodered-cloudantnode.jpg](https://qiita-image-store.s3.amazonaws.com/0/73397/6fee00d4-53e5-94dc-bbd7-1160a85f91c3.jpeg) | Cloudantからのデータ取得 |
| http responseノード | ![nodered-httpresponse.jpg](https://qiita-image-store.s3.amazonaws.com/0/73397/d6ea8368-3265-73b3-6c46-154778b19759.jpeg) | クライアントへレスポンス送信 |
| Debugノード | ![nodered-debug.jpg](https://qiita-image-store.s3.amazonaws.com/0/73397/449ea1c7-f145-1318-2901-afb4a7afc6d1.jpeg) | 出力結果確認 |

### httpノードの構成

httpノードは、以下のとおり構成しています。HTTPのGETメソッドを利用し、URLのパスを*/sensordata*としています。ここで設定したパスを含むURLは、Node-REDフローエディターのFQDNにパスを加えたものとなります。
たとえば、フローエディターのURLが*http://sample.mybluemix.net/red/*の場合、ここで設定するGETリクエストのURLは、*http://sample.mybluemix.net/sensordata*となります。

![nodered-cloudant15.jpg](https://qiita-image-store.s3.amazonaws.com/0/73397/b89e345d-0a83-261e-0a6a-b2169c2e1c26.jpeg)

### functionノードの構成
Cloundantの検索に使用する文字列を生成します。以下のJSON形式のデータをCloudantの検索に使用します。

```
{
  "query": "[ start_date TO end_date ]",
  "limit": 200
}
```

queryの部分にLuceneの記法の検索文字列を入力します。今回は、*start_date*と*end_date*の部分が、HTTP GETリクエストのクエリーパラメーターで受け取る値を使用するようにします。
Search Indexのクエリー結果は、デフォルトで25件までしか返さないようになっています。この制限を変更するために、*limit*を*200*としています。残念ながら、制約として、200を超える結果を返すことはできません。

functionノードに登録するスクリプトは、以下のとおりです。

```
msg.payload = {
    "query": "timestamp:[" + msg.payload.start + " TO " + msg.payload.end + "]",
    "limit": 200
}

return msg;
```

### Cloudantノードの構成
Cloudantノードの設定は以下のとおりです。

| 設定項目 | 内容 |
| :-- | :-- |
| Service | Bluemix上に作成されたCloudantのサービス名を選択します |
| Database | Cloudantに作成したデータベース名である*sensordata*を入力します |
| Search by | *search index*を選択します。対象のIndexとして、Search Indexの作成で作成してIndexを指定します。 |
| Name | ノードに付ける名前です。任意の値で問題ありません。 |

入力例は以下のとおりです。
![nodered-cloudant16.jpg](https://qiita-image-store.s3.amazonaws.com/0/73397/9e2f7e51-aab4-f139-ba91-ea926dd968cd.jpeg)


### http responseノードの構成
http responseノードは、ノードの名前以外に設定項目はありません。任意の名前をつけてください。

### （参考）サンプルフローのインポート
以下のJSONを、[Node-RED小ワザ集](http://qiita.com/asmanabu/items/d9ba9ff0fca745c8c216)の[小ワザ1. フローのインポート](http://qiita.com/asmanabu/items/d9ba9ff0fca745c8c216#%E5%B0%8F%E3%83%AF%E3%82%B61-%E3%83%95%E3%83%AD%E3%83%BC%E3%81%AE%E3%82%A4%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%88)の方法を使ってインポートすることで、サンプルフローを復元できます。

```
[{"id":"8adf6400.6d175","type":"http in","name":"Get Sensor Data","url":"/sensordata","method":"get","x":125,"y":359,"z":"56be2dc6.6f2e4c","wires":[["bce3b962.ddd648"]]},{"id":"5a004193.4e4b7","type":"cloudant in","service":"IoTFSample-cloudantNoSQLDB","cloudant":"","name":"Get Sensor Data from Cloudant","database":"sensordata","search":"_idx_","design":"Index","index":"IndexByTimestamp","x":367,"y":439,"z":"56be2dc6.6f2e4c","wires":[["43775b51.c3a424","7b27b5c9.f5f754"]]},{"id":"43775b51.c3a424","type":"http response","name":"Response to Client","x":636,"y":439,"z":"56be2dc6.6f2e4c","wires":[]},{"id":"7b27b5c9.f5f754","type":"debug","name":"Check Output","active":false,"console":"false","complete":"payload","x":560,"y":361,"z":"56be2dc6.6f2e4c","wires":[]},{"id":"bce3b962.ddd648","type":"function","name":"Create Query","func":"msg.payload = {\n    \"query\": \"timestamp:[\" + msg.payload.start + \" TO \" + msg.payload.end + \"]\",\n    \"limit\": 200\n}\n\nreturn msg;","outputs":1,"valid":true,"x":318,"y":359,"z":"56be2dc6.6f2e4c","wires":[["5a004193.4e4b7"]]}]
```

### フローのデプロイ
以上でフローの作成は完了です。フローエディター右上の ![nodered-cloudant08.jpg](https://qiita-image-store.s3.amazonaws.com/0/73397/68fa9359-0d5f-0b48-e39c-9f49a1c7da50.jpeg) をクリックして、フローをデプロイします。

## 3. 動作確認
ブラウザを利用して、動作を確認します。クエリーパラメーターとして検索開始日時の*start*と検索終了日時の*end*を指定して、httpノードを構成した際に入力したURLにアクセスします。
アクセスするURLの例です。

```
http://sample.mybluemix.net/sensordata?start=2015-04-22T19:30:00Z&end=2015-04-22T19:36:00Z
```

以下のレスポンスを取得することができました。

```
[
  {
    "_id": "40384c3ef6fb489997adc0530819e2d3",
    "_rev": "1-6033dce739fee18f34063d7345fe61ed",
    "timestamp": "2015-04-22T19:30:15Z",
    "temp": 44,
    "humidity": 51,
    "objectTemp": 32
  },
  {
    "_id": "38ab698d4e8f3c6e5e4f011db2cb5082",
    "_rev": "1-c3118a250f8f40f56c23b27472403f1f",
    "timestamp": "2015-04-22T19:30:41Z",
    "temp": 44,
    "humidity": 51,
    "objectTemp": 32
  },
  {
    "_id": "9f84503729658d77f5d28fd3c4a782a2",
    "_rev": "1-c6a3a5e68e8aebff97e5f289925e2460",
    "timestamp": "2015-04-22T19:30:47Z",
    "temp": 44,
    "humidity": 51,
    "objectTemp": 32
  },
  {
    "_id": "0f3c227bbc36bbec8e31b2eb877bdcd1",
    "_rev": "1-4826ef6ded531287516107891033eee7",
    "timestamp": "2015-04-22T19:31:13Z",
    "temp": 44,
    "humidity": 51,
    "objectTemp": 32
  }
]
```