CloudantのデータをCSVでダウンロードする方法

#はじめに
IBM Cloud上のCloudantに保存したデータをCSVに変換してダウンロードする方法です。
Cloudantにアクセスして、保存されてるJsonをCSVに変換するプログラムを書くという方法もありますが、ここではCloudantのDesign Document Viewというものを使って、CSVに変換する方法を解説します。

Design Document Viewを使うと、ブラウザーから直接ダウンロードができるようになります。

この内容を元に実施した手順です。
https://developer.ibm.com/clouddataservices/2015/09/22/export-cloudant-json-as-csv-rss-or-ical/

#前提
IBM Cloud上にCloudantを作成する手順は含みません。

- 事前に、「Cloudant-csvtest」というCloudantのインスタンスを作成しています。
![cloudant01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148302/bf16a79a-98d0-89ca-eeaf-875ad085f811.png)

- Cloudant Dashobardから、「csvtest」というDatabaseを作成しています。
![cloudant02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148302/6be2de78-06ce-491b-0509-80d077ff546a.png)

###サンプルデータ
以下のようなJSONデータをデータベースに保存しています。

```
{
  "_id": "89a66bae620c33d653a0c02f2add5b4a",
  "_rev": "1-bba9e83dbb192ea0c05e13f0d9296322",
  "product": "Cut",
  "customer": "Lady Catherine de Bourgh",
  "date": "2015-09-29 16:00:00",
  "duration": 1,
  "stylist": "Mandy",
  "branch": "Stockport",
  "cost": 25,
  "paid": false
}
```

![cloudant03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148302/f1f2f25d-cf91-0c1c-9cc5-7e1680bedc9f.png)

#Design Document Viewの作成
「Design Documents」から「New View」をクリックします。
![cloudant04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148302/2738b329-db0b-5bd1-309f-897d6b522ae7.png)

_design/ と Index name に任意の名前を付けて「Create Document and then Build Index」をクリックします。
※ここで指定する名前は後ほどCSVダウンロードで使います。
![cloudant05.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148302/6667e320-3ee0-abed-b2a5-1fe4afa63483.jpeg)

こんな感じになります。
１行目がDesign View、２行目がサンプルデータです。
Design ViewのDocumentをクリックして内容を編集します。
![cloudant06.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148302/2b89e96a-1b45-3cde-07ed-0eb3e5187d32.jpeg)

#コードの埋め込み
以下の部分にコードを書いていきます。
![cloudant07.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148302/98a17a81-e0b1-76e2-0dcb-97b32b5dbfd4.jpeg)

以下のコードをコピーして、

```
  "lists": {
    "csvtest": "function(head, req) { var row; var first = true; start({ headers: { 'Content-Type': 'text/csv'},}); while(row = getRow()) { var doc = row.doc;  if (first) {  send(Object.keys(doc).join(',') + '\\n'); first = false;} var line = '';  for(var i in doc) { if (line.length > 0) { line += ',';　} var val = doc[i]; if (typeof val == 'string' && val.indexOf(',') > -1) { line += '\"' + val.replace(/\"/g, '\"\"') + '\"';  } else { line += val; } } line += '\\n'; send(line); } }"
  },
```

> <font color="red"><b>注意</b></font>
> <ul><li>JavaScriptで書く必要があります。
> <li>改行やタブを含めることはできません。
> <li>コード内で必要となる改行はバックスラッシュ(\\)でエスケープする必要があります。
> <li>全て1行に記述する必要があります。
そのためとても読みにくい。。。
手間ですが、予め他のエディタで正常に動くことを確認してからここにコピペすると良いと思います。</li></ul>


こんな感じにそのままペースとし、「Save Changes」をクリックします。
![cloudant08.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148302/de54e7f5-cb41-3b35-4a8e-cde029cb8f3e.jpeg)

#CSVダウンロード
その後、以下のようなURLにアクセスするとデータがCSVとなってダウンロードされます。

```
https://f9c48dfb-2248-*************-bluemix.cloudant.com/csvtest/_design/view1/_list/csvtest/new-view1?include_docs=true
```

> f9c48d から始まる値：CloudantのExternal Endpoint（CloudantのURL）
> csvtest : データベース名
> \_desgin：固定
> view1：Design view名
> \_list：固定
> csvtest：コピペした時に指定したlists内の名前
> new-view1：索引名
> include_docs=true：ドキュメントを含めるというオプション

###CSV例
```
_id,_rev,product,customer,date,duration,stylist,branch,cost,paid
e1cd4c4348a57af329e79ec693ff394b,1-bba9e83dbb192ea0c05e13f0d9296322,Cut,Lady Catherine de Bourgh,2015-09-29 16:00:00,1,Mandy,Stockport,25,false
```

###補足
読みにくかったコードを読みやすく整形したのがこちら。

```javascript
function(head, req) {
  var row;
  var first = true;
 
  // output HTTP headers
  start({
    headers: {  'Content-Type': 'text/csv'  },
  });
  
  // iterate through the result set
  while(row = getRow()) { 
    // get the doc (include_docs=true)
    var doc = row.doc;
    // if this is the first row
    if (first) {
      // output column headers
      send(Object.keys(doc).join(',') + 'n');
      first = false;
    }
    // build up a line of output
    var line = '';
    // iterate through each row
    for(var i in doc) {
      // comma separator
      if (line.length > 0) {
        line += ',';
      }
      // output the value, ensuring values that themselves
      // contain commas are enclosed in double quotes
      var val = doc[i];
      if (typeof val == 'string' && val.indexOf(',') >  -1) {
        line += '"' + val.replace(/"/g,'""') + '"';
      } else {
        line += val;
      }
    }
    line += 'n';
    // send  the line
    send(line);
  }
};
```

### お断り
このサイトの掲載内容は私自身の見解であり、必ずしも所属会社の立場、戦略、意見を代表するものではありません。 記事は執筆時点の情報を元に書いているため、必ずしも最新情報であるとはかぎりません。 記事の内容の正確性には責任を負いません。自己責任で実行してください。