Más contenido relacionado
La actualidad más candente (20)
Similar a はじめてのCouch db (20)
はじめてのCouch db
- 1. はじめてのCouchDB
黒田英二
http://blog.kuroda.me/eiji/
10 May 2012
1
- 9. Mac OSX 10.7+
必要な環境
Xcode4.3+のCommand Line Tools
ruby 1.9.3
brewでインストール
# 以前にCouchDBをインストールしてたら
brew remove --force openssl erlang couchdb icu4c spidermonkey nspr
# インストール
brew update
brew install erlang --no-docs
brew install couchdb
9
- 10. 起動方法
#初めてインストールしたら
mkdir -p ~/Library/LaunchAgents
cp /usr/local/Cellar/couchdb/1.2.0/Library/LaunchDaemons/org.apache.couchdb.plist
~/Library/LaunchAgents/
launchctl load -w ~/Library/LaunchAgents/org.apache.couchdb.plist
#既にインストールしてたら
launchctl unload -w ~/Library/LaunchAgents/org.apache.couchdb.plist
cp /usr/local/Cellar/couchdb/1.2.0/Library/LaunchDaemons/org.apache.couchdb.plist
~/Library/LaunchAgents/
launchctl load -w ~/Library/LaunchAgents/org.apache.couchdb.plist
#自動起動は下記
sudo launchctl list org.apache.couchdb >/dev/null 2>&1 &&
sudo launchctl unload -w /Library/LaunchDaemons/org.apache.couchdb.plist
sudo cp /usr/local/Cellar/couchdb/1.2.0/Library/LaunchDaemons/org.apache.couchdb.plist
/Library/LaunchDaemons/
sudo launchctl load -w /Library/LaunchDaemons/org.apache.couchdb.plist
#もしくは、下記で
couchdb
10
- 13. APIのURL表記について
太字のURLはAPIの例を記述
Method URL [JSON] で記述
URLの次行にJSONがある場合はレスポンスを示す
PUT /members
curl -X PUT ‘http://localhost:5984/members’
PUT /members {“name”:”eiji”}
curl -X PUT -d ‘{“name”:”eiji”}’ ‘http://...’
curlでJSONをPOST/PUTする時は次のオプションが必要
-H 'Content-type:application/json'
13
- 14. DBを作る
DB名に使える文字
アルファベットの小文字
数字
_,$,(,),+,-,/
DB名がmembersの
場合
PUT /members
14
- 17. リビジョン番号
CouchDBのドキュメントは削除されず追加のみ (※1)
DocID+リビジョン番号(RevID)で一意
DocIDのみ取得できるドキュメントは、最新のもの(※2)
“id”:”eiji”, “name”:”eiji”, “rev”:”1-123”
新規追加時のDoc
“id”:”eiji”, “name”:”test”, “rev”:”2-abc”
1回目の更新
更新や削除では、
“id”:”eiji”, “name”:”kuroda”, “rev”:”3-efg”
DocID+RevIDを指定
2回目の更新=最新
※1 空間最適化のために、DB別に古いリビジョンを物理削除するコマンドがある
※2 コンフリクトが発生してない場合
17
- 19. 一覧取得
futon上はDBの初期画面
DocID,key,valueが返る
valueはリビジョン番号
_all_docsは予約語
GET /members/_all_docs
{"total_rows":2,"offset":0,"rows":[
{"id":"7544...","key":"7544...","value"{"rev":"1-1e60813c6ca45903.."}},
{"id":"eiji","key":"eiji","value":{"rev":"1-96277b971e..."}}
]}
ソート順を逆にしたり、取得件数を指定するオプションあり
19
- 24. バルク取得
複数のドキュメントを1回のリクエストで取得
_all_docs に POST で DocIDs を配列で投げる
戻ってくるJSON形式は_all_docsと同じ
POST /members/_all_docs {“keys”:[“eiji”,”hoge”]}
{"total_rows":2,"offset":0,
"rows":[
{"id":"eiji","key":"eiji","value":{"rev":"abc123"},
{"id":"hoge","key":"hoge","value":{"rev":"efg987”}
]
}
24
- 25. バルク追加、更新、削除
複数のドキュメントの追加、更新、削除を1回のリクエストで可能
更新、削除は各ドキュメントのリビジョン番号を指定
次のようなファイル(data.json)があるとして
追加
{"docs":[
{"_id":"hoge", "name":"hoge"}, 更新
{"_id":"eiji", "_rev":"abc123", "name":"eiji"},
{"_id":"kuroda", "_rev":"efg987", “_deleted”:true},
]}
削除
POST /members/_bulk_docs @data.json
[
{"ok":true,"id":"hoge","rev":"1-c1b7ada1c9b31..."},
{"ok":true,"id":"eiji","rev":"2-c1b7ada1c9b31..."},
{"ok":true,"id":"kuroda","rev":"2-a84c9f34a74285a2..."}
]
25
- 27. コンフリクト状態
first.json second.json “id”:”abc”は
{"docs":[ {"all_or_nothing":true,"docs":[ 中身が違うドキュメン
{"_id":"abc", "name":"abc"}, {"_id":"abc", "name":"ABC"}, ト
{"_id":"def", "name":"def"} {"_id":"def", "name":"def"}
]} ]}
POST /members/_balk_docs @first.json コンフリクトが発生したが
[ {"ok":true,"id":"abc","rev":"1-123xxx"},
レスポンスは全件OK
{"ok":true,"id":"def","rev":"1-123yyy"}]
しかも、全部保存されてる
POST /members/_balk_docs @second.jso
[ {"ok":true,"id":"abc","rev":"1-123zzz"},
{"ok":true,"id":"def","rev":"1-123yyy"}] conflicts=trueは
普通に取得可能 コンフリクトしてるかどうかを
GET /members/abc
{"_id":"abc","_rev":"1-123xxx","name":"abc"} 属性に含めて返すオプション
GET /members/abc?conflicts=true
{"_id":"abc","_rev":"1-123xxx","name":"abc","_conflicts":["1-123zzz"]}
GET /members/def?conflicts=true コンフリクトしてる
{"_id":"def","_rev":"1-123yyy","name":"def"}
コンフリクトしてない
27
- 30. デザイン・ドキュメント
_design/people “people”というデザイン名
“_design/people”というDocID
“all”: “map”:”function(doc){..}”
“all”というview名
“over20”: “map”:”function(doc){..}”
“map”:”function(doc){..}” 実際に表示する際のURL
“total_age”: GET /{dbname}/_design/people/_view/total_age
“reduce”:”function(keys,.
30
- 31. ところでMap&Reduce
大量のデータを分散して処理する仕組
み
map reduce
“バナナ”, 300円 “りんご”, 400円 400円+300円
“おにぎり”, 150円
“りんご”, 400円
150円+700円
“ぶどう”, 700円
“おにぎり”, 150円 “バナナ”, 300円
“ぶどう”, 700円
1550円
31
- 34. 買い物リストでサンプル作成
date category item price
5/10 果物 バナナ 300
5/10 魚 鯛 1000
5/11 果物 みかん 400
5/11 果物 バナナ 250
5/12 魚 鯛 900
34
- 35. 最も単純なmap
emitで指定したkey
map 結果
function(doc){ key id date category item price
emit(null, doc)
} null 123xx 5/10 果物 バナナ 300
null 234xx 5/10 魚 鯛 1000
null 345xx 5/11 果物 みかん 400
•mapにドキュメントがパラメータとして来る
null 456xx 5/11 果物 バナナ 250
•reduceに渡すのはemitメソッド null 567xx 5/12 魚 鯛 900
•検索結果の行数(total_rows)も出力
•結果はJSONで返る mapしたドキュメントのdocID
{"total_rows":5,"offset":0,"rows":[
{"id":"123xx","key":null,
"value":{
"_id":"123xx","_rev":"1-123xx","date":"5/10", "category":"果物","item":"バナナ","price":300
}
},....
35
- 36. 値段の順にソート
map 結果
function(doc){ key id date category item price
emit(doc.price, doc);
} 250 456xx 5/11 果物 バナナ 250
300 123xx 5/10 果物 バナナ 300
400 345xx 5/11 果物 みかん 400
900 567xx 5/12 魚 鯛 900
1000 234xx 5/10 魚 鯛 1000
•key+idの降順
•逆順にする場合は descending=true
例) GET /items/_design/items/_view/by_price?descending=true
36
- 37. 果物だけ抽出
map 結果
function(doc){ key id date category item price
if(doc.category == ”果物”)
null 123xx 5/10 果物 バナナ 300
emit(null, doc);
}
null 345xx 5/11 果物 みかん 400
null 456xx 5/11 果物 バナナ 250
37
- 38. 値段を合計する
map 結果
function(doc){ key value
emit(null, doc.price);
null 2850
}
{"rows":[
{"key":null, value:2850}
reduce ]}
function(keys, values){ keysには次のような値が入る
return sum(values);
[[null, “123xx”], [null, “234xxx”], ..]
}
valuesには次のような値が入る
sumは数値の配列を合計するメソッド [300, 1000, 400, 250, 900]
returnで1つの値を返すように作る
38
- 39. 日付毎に値段を合計
map 結果
function(doc){ key value
emit(doc.date, doc.price);
} 5/10 300
5/11 1650
reduce 5/12 900
function(keys, values){ 次のように3回に分けて reduce が呼ばれる
return sum(values);
} keys [[“5/10”, “123xxx”]]
values [300]
普通に呼び出すと合計の2850だけが戻る keys [[“5/11”, “123xx”], [“5/11”, “234xxx”], ..]
key値毎の塊をグループと言う。 values [250, 400, 1000]
グループ毎に出力するには、次のように呼び出す。 keys [[“5/12”, “123xx”]]
values [900]
GET /.../_view/daily_cost?group=true
39
- 40. 日付+カテゴリ毎に値段を合
map 結果
function(doc){ key value
emit([doc.date, doc.category], doc.price);
[“5/10”,”果物”] 300
}
[“5/11”,”果物”] 650
[“5/11”,”魚”] 1000
reduce [“5/12”,”魚”] 900
function(keys, values){
return sum(values);
}
グループに深さができる。
1階層目は日付ごと、2階層目は日付+カテゴリ毎
GET /.../_view/dail_cat_cost?group=true #日付+カテゴリ毎
GET /.../_view/dail_cat_cost?group=true&group_level=2 #日付+カテゴリ
毎
GET /.../_view/dail_cat_cost?group=true&group_level=1 #日付毎
40
- 41. カテゴリ毎の件数を調べる
map 結果
function(doc){ key value
emit(doc.category, 1);
} 果物 3
魚 2
reduce
function(keys, values){ 次のようにreduceが呼ばれる
return sum(values);
} keys [[“果物”, “123xxx”], [“果物”,...]]
values [1,1,1]
keys [[“魚”, “123xx”], [“魚”, “234xxx”]]
values [1,1]
41
- 44. 失敗するcount
下記の処理でも件数が求まるように思えるが
実際には想定通り動かない場合がある。
map reduce
function(doc){ function(keys, values, rereduce){
emit(doc.category, 1); return values.length;
} }
再帰呼び出しの際に
5個のりんごが2個とカウントされてしま
reduceの戻り値の配列がvaluseに入る
う
keys [[“りんご”]...] values [1,1,1] rereduce false
rereduce処理
values.length -> 3
keys null values [3,2] rereduce true
keys [[“りんご”]...] values [1,1] rereduce false
values.length -> 2
values.length -> 2
- 45. 成功するcount①
map reduce
function(doc){ function(keys, values, rereduce){
emit(doc.category, 1); return sum(values);
} }
keys [[“りんご”]...] values [1,1,1] rereduce false rereduce処理
sum(values) -> 3
keys null values [3,2] rereduce true
keys [[“りんご”]...] values [1,1] rereduce false
sum(values) -> 2
sum(values) -> 5
- 46. 成功するcount②
map reduce
function(doc){ function(keys, values, rereduce){
emit(doc.category, 1); if(rereduce)
} return sum(values);
else
return values.length;
}
keys [[“りんご”]...] values [1,1,1] rereduce false rereduce処理
values.length -> 3
keys null values [3,2] rereduce true
keys [[“りんご”]...] values [1,1] rereduce false
values.length -> 2
sum(values) -> 5
- 47. viewについて補足
sum,countには組込のメソッド {“map”:”function(doc){emmit(doc,1)}”
“reduce”:”_count”},
がある {“map”:”function(doc){emmit(doc,doc.price)}”
“reduce”:”_sum”}
デバッグ用にlogメソッドがあ
function(keys, values, rereduce){
る。ログファイルに出力される。 log(values);
return sum(values);
}
Validationが設定できる
Document Update Validation
一括Updateの方法がある
Document Update Handler
Notas del editor
- \n
- \n
- \n
- \n
- \n
- \n
- \n
- \n
- \n
- \n
- \n
- \n
- \n
- \n
- \n
- \n
- \n
- \n
- \n
- \n
- \n
- \n
- \n
- \n
- \n
- \n
- \n
- \n
- \n
- \n
- \n
- \n
- \n
- \n
- \n
- \n
- \n
- \n
- \n
- \n
- \n
- \n
- \n
- \n
- \n
- \n
- \n
- \n
- \n
- \n
- \n
- \n
- \n