7つのデータベース7つの世界 CouchDB メモ


# はじめに
[7つのデータベース 7つの世界](http://www.amazon.co.jp/gp/product/4274069087/ref=as_li_qf_sp_asin_tl?ie=UTF8&camp=247&creative=1211&creativeASIN=4274069087&linkCode=as2&tag=nownabe-22)の第5章 CouchDBのメモです。

# 1日目
## CouchDB インストール
http://qiita.com/nownabe/items/2127ca44ba0422002046

## 1日目の宿題
### 調べてみよう 1
> CouchDB HTTP Document APIのオンラインドキュメントを探してみよう。

http://docs.couchdb.org/en/latest/api/index.html

### 調べてみよう 2
> これまでに、GET・POST・PUT・DELETEを使ってきたが、他のHTTPコマンドはサポートされているだろうか？

以下のメソッドがサポートされている。

* GET
* HEAD: GETのボディがついてこない版
* POST
* PUT
* DELETE
* COPY: コピーする

http://docs.couchdb.org/en/latest/api/basics.html#request-format-and-responses

### やってみよう 1
> cURLと任意の_idを使って、新しいドキュメントをmusicデータベースにPUTしてみよう

```bash
$ curl -i -X PUT "http://localhost:5984/music/Angra" \
> -H "Content-Type: application/json" \
> -d '{
>   "_id": "Angra",
>   "name": "Angra",
>   "albums": ["Rebirth", "Temple of Shadows", "Aurora Consurgens"]
> }'
HTTP/1.1 201 Created
Server: CouchDB/1.0.4 (Erlang OTP/R14B04)
Location: http://localhost:5984/music/Angra
Etag: "1-56c1d0e90fd4db4082102ac053a2fc0f"
Date: Sun, 28 Sep 2014 09:19:45 GMT
Content-Type: text/plain;charset=utf-8
Content-Length: 68
Cache-Control: must-revalidate

{"ok":true,"id":"Angra","rev":"1-56c1d0e90fd4db4082102ac053a2fc0f"}
```

### やってみよう 2
> curlを使って、任意の名前のデータベースを作成してみよう。そして、そのデータベースを削除してみよう。

```bash
nownabe@7dbs:~$ curl -i -X PUT "http://localhost:5984/ytmy"
HTTP/1.1 201 Created
Server: CouchDB/1.0.4 (Erlang OTP/R14B04)
Location: http://localhost:5984/ytmy
Date: Sun, 28 Sep 2014 09:23:34 GMT
Content-Type: text/plain;charset=utf-8
Content-Length: 12
Cache-Control: must-revalidate

{"ok":true}

nownabe@7dbs:~$ curl -q -X GET "http://localhost:5984/ytmy" | jq "."
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
104   209  104   209    0     0  92355      0 --:--:-- --:--:-- --:--:--  204k
{
  "committed_update_seq": 0,
  "disk_format_version": 5,
  "db_name": "ytmy",
  "doc_count": 0,
  "doc_del_count": 0,
  "update_seq": 0,
  "purge_seq": 0,
  "compact_running": false,
  "disk_size": 79,
  "instance_start_time": "1411896214206138"
}

nownabe@7dbs:~$ curl -i -X DELETE "http://localhost:5984/ytmy"
HTTP/1.1 200 OK
Server: CouchDB/1.0.4 (Erlang OTP/R14B04)
Date: Sun, 28 Sep 2014 09:26:05 GMT
Content-Type: text/plain;charset=utf-8
Content-Length: 12
Cache-Control: must-revalidate

{"ok":true}

nownabe@7dbs:~$ curl -X GET "http://localhost:5984/ytmy" | jq "."
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0    44    0    44    0     0  16923      0 --:--:-- --:--:-- --:--:-- 44000
{
  "reason": "no_db_file",
  "error": "not_found"
}
```

* [データベース作成API](http://docs.couchdb.org/en/latest/api/database/common.html#put--db)
* [データベース削除API](http://docs.couchdb.org/en/latest/api/database/common.html#delete--db)

### やってみよう 3
> cURLを使って、テキストドキュメントが添付されたドキュメントを作成してみよう。最後に、その添付を返すようなcURLのリクエストを作って実行してみよう。

```bash
nownabe@7dbs:~$ echo 'CouchDB Yattemiyo!' > ytmy.txt

nownabe@7dbs:~$ curl -X PUT "http://localhost:5984/ytmy"
{"ok":true}

nownabe@7dbs:~$ curl -i -X PUT "http://localhost:5984/ytmy/ytmy3/ytmy.txt" -H "Content-Type: text/plain" -d @ytmy.txt
HTTP/1.1 201 Created
Server: CouchDB/1.0.4 (Erlang OTP/R14B04)
Location: http://localhost:5984/ytmy/ytmy3/ytmy.txt
Etag: "1-5e626c39b685094d34e599f6325df727"
Date: Sun, 28 Sep 2014 09:32:50 GMT
Content-Type: text/plain;charset=utf-8
Content-Length: 68
Cache-Control: must-revalidate

{"ok":true,"id":"ytmy3","rev":"1-5e626c39b685094d34e599f6325df727"}

nownabe@7dbs:~$ curl -X GET "http://localhost:5984/ytmy/ytmy3" | jq "."
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
153   153  153   153    0     0  58042      0 --:--:-- --:--:-- --:--:--  149k
{
  "_attachments": {
    "ytmy.txt": {
      "stub": true,
      "length": 18,
      "revpos": 1,
      "content_type": "text/plain"
    }
  },
  "_rev": "1-5e626c39b685094d34e599f6325df727",
  "_id": "ytmy3"
}

nownabe@7dbs:~$ curl -i -X GET "http://localhost:5984/ytmy/ytmy3/ytmy.txt"
HTTP/1.1 200 OK
Server: CouchDB/1.0.4 (Erlang OTP/R14B04)
ETag: "1-5e626c39b685094d34e599f6325df727"
Date: Sun, 28 Sep 2014 09:35:34 GMT
Content-Type: text/plain
Content-Length: 18
Cache-Control: must-revalidate

CouchDB Yattemiyo!
```

* [添付ファイルアップロードAPI](http://docs.couchdb.org/en/latest/api/document/attachments.html#put--db-docid-attname)
* [添付ファイル取得API](http://docs.couchdb.org/en/latest/api/document/attachments.html#get--db-docid-attname)

# 2日目
## Ruby でデータを CouchDB にインポート
libxml-ruby gemのインストール。

```bash
$ sudo yum install -y libxml2-devel
$ gem install libxml-ruby couchrest
```

## 2日目の宿題
### 調べてみよう 1
Template viewでやってみた。

```javascript
function(doc) {
  emit(doc.albums, doc.name)
}
```

できました。

Arrayもサポートされていて、reduceするときにgroup_levelというパラメータと使うみたいです。
http://docs.couchdb.org/en/latest/couchapp/views/intro.html
これは便利そうですね。

### 調べてみよう 2
いろいろあります。
http://docs.couchdb.org/en/latest/api/ddoc/views.html

### やってみよう 1
```javascript:MapFunction
function(doc) {
  if (doc.random) {
    emit(doc.random, doc.name)
  }
}
```

### やってみよう 2
```bash
nownabe@7dbs:~$ curl -s 'http://localhost:5984/music/_design/artists/_view/random?limit=1&startkey='`ruby -e 'print rand'` | jq "."
{
  "rows": [
    {
      "value": "Curtis Chris Roman",
      "key": 0.4759395726706507,
      "id": "439012"
    }
  ],
  "offset": 43,
  "total_rows": 100
}
nownabe@7dbs:~$ curl -s 'http://localhost:5984/music/_design/artists/_view/random?limit=1&startkey='`ruby -e 'print rand'` | jq "."
{
  "rows": [
    {
      "value": "Bleacher",
      "key": 0.5446379390099795,
      "id": "274"
    }
  ],
  "offset": 52,
  "total_rows": 100
}
nownabe@7dbs:~$ curl -s 'http://localhost:5984/music/_design/artists/_view/random?limit=1&startkey='`ruby -e 'print rand'` | jq "."
{
  "rows": [
    {
      "value": "uv330",
      "key": 0.41952107761776813,
      "id": "349359"
    }
  ],
  "offset": 36,
  "total_rows": 100
}
```

### やってみよう 3
```bash:_design/random/_view/album
function(doc) {
  doc.albums.forEach(function(album){
    if (album.random) emit(album.random, album.name)
  })
}
```

```bash:_design/random/_view/track
function(doc) {
  doc.albums.forEach(function(album){
    if (album.tracks) {
      album.tracks.forEach(function(track) {
        emit(track.random, track.name)
      })
    }
  })
}
```

```bash:_design/random/_view/tag
function(doc) {
  doc.albums.forEach(function(album){
    if (album.tracks) {
      album.tracks.forEach(function(track) {
        track.tags.forEach(function(tag) { emit(tag.random, tag.idstr) })
      })
    }
  })
}
```