couchdb.apache.org says ...
... let's see!
couchdb.apache.org says ...
... let's see!
Andy Wenk
May 10, 2012 - JUG-OSTFALEN
/ Andy Wenk
/ Senior Developer at SinnerSchrader Hamburg
/ Having fun with Ruby, Rails, JavaScript, HTML5, CSSx, PHP
/ ... and CouchDB!
/ had fun with PostgreSQL also
/ get in touch:
andy@nms.de
andreas.wenk@sinnerschrader.com
G+
@awenkhh
couchdb-buch.de
CouchDB is built of the Web
Relational databases have been very successful in the past, and are likely to remain so, but in a certain sub-set of usage scenarios, non-relational systems are starting to take their place.
see also: http://kkovacs.eu/cassandra-vs-mongodb-vs-couchdb-vs-redis/
Usage:
Usage:
Usage:
Usage:
Reading: http://riakhandbook.com/ by Mathias Meyer (@roidrage)
Usage:
try it: http://try.redis-db.com/
| Language | Access | designed for | |
| CouchDB | Erlang | HTTP / REST | consistency, ease of use |
| Cassandra | Java | driver, thrift | Best of BigTable and Dynamo |
| MongoDB | C++ | driver | good parts of SQL |
| Neo4J | Java | REST / embedded | relations, search |
| riak | Erlang | REST / driver | Fault tolerance, tunable |
| redis | C | driver / TCP | speed |
MVCC - Multi Version Concurrency Control
ACID
... later
CAP Theorem by Dr. Eric Brewer - approved by Seth Gilbert and Nancy Lynch
In CouchDB when used as distributed system: AP
Mac OS X - homebrew
brew update
brew upgrade
brew install couchdb
brew unlink couchdb
brew install couchdb
couchdb -V
couchdb - Apache CouchDB 1.2.0
Mac OS X - MacPorts (rethink!)
sudo port install couchdb
sudo port upgrade couchdb
Linux
Instructions for UbuntuWindows
InstructionsHello CouchDB:
curl -X GET http://localhost:5984
{"couchdb":"Welcome","version":"1.2.0"}
All DB's
curl -X GET http://localhost:5984/_all_dbs
["_replicator","_users","kassenbuch","multi-ids"]
Create a DB
curl -X PUT http://localhost:5984/jug
{"ok":true}
curl -X GET http://localhost:5984/_all_dbs
["_replicator","_users","jug","kassenbuch","multi-ids"]
Creating a document with POST
curl -X POST http://localhost:5984/jug/ -H "Content-Type: application/json" -d '{}'
{"ok":true,
"id":"03cab906fa68e852be833ebb17001cd4",
"rev":"1-967a00dff5e02add41819138abb3284d"}
id
rev
Annotation
Creating a document with PUT with usage of a uuid ...
curl -X GET http://localhost:5984/_uuids
{"uuids":["03cab906fa68e852be833ebb17000ff8"]}
curl -X PUT http://localhost:5984/jug/03cab906fa68e852be833ebb17000ff8 -d '{}'
{"ok":true,
"id":"03cab906fa68e852be833ebb17000ff8",
"rev":"1-967a00dff5e02add41819138abb3284d"}
... or with a own id
curl -X PUT http://localhost:5984/jug/first_doc -d '{}'
{"ok":true,"id":"first_doc","rev":"1-967a00dff5e02add41819138abb3284d"}
Annotation
Updating a document with PUT
curl -X PUT http://localhost:5984/jug/first_doc
-d '{"_rev":"1-967a00dff5e02add41819138abb3284d",
"some-content":"Hey how are you dude?"}'
{"ok":true,"id":"first_doc","rev":"2-65ef50076c98c6817fb3ca97c87d8b66"}
possible to use the if-match header
-H "if-match:1-967a00dff5e02add41819138abb3284d"
Annotation
Difference between POST and PUT
Annotation
Deleting a document with GET
curl -X DELETE http://localhost:5984/jug/first_doc?rev=3-73846195cbf86c1a3b94b6c04b6bebc0
{"ok":true,"id":"first_doc","rev":"4-9853b2dfc30eb372590c60a339124cfd"}
possible to use the if-match header
-H "if-match:3-73846195cbf86c1a3b94b6c04b6bebc0"
document is not deleted physically but marked with --deleted: true
curl -X GET http://localhost:5984/jug/first_doc
{"error":"not_found","reason":"deleted"}
Add attachment to document
curl -X PUT http://localhost:5984/jug/second_doc -d '{}'
{"ok":true,"id":"second_doc","rev":"1-967a00dff5e02add41819138abb3284d"}
curl -X PUT http://localhost:5984/jug/second_doc/mvcc.png?rev=1-967a00dff5e02add41819138abb3284d
--data-binary @mvcc.png
-H "Content-Type: image/png"
{"ok":true,"id":"second_doc","rev":"2-f488b45f8c02c4da096d23739051d428"}
Receive attachment from document
curl -i -X GET http://localhost:5984/jug/second_doc/
HTTP/1.1 200 OK
Server: CouchDB/1.2.0 (Erlang OTP/R15B01)
ETag: "2-f488b45f8c02c4da096d23739051d428"
Date: Sun, 06 May 2012 21:03:26 GMT
Content-Type: text/plain; charset=utf-8
Content-Length: 200
Cache-Control: must-revalidate
{"_id":"second_doc",
"_rev":"2-f488b45f8c02c4da096d23739051d428",
"_attachments":
{"mvcc.png":
{"content_type":"image/png",
"revpos":5,
"digest":"md5-RJsN7gjQubg+iqLe96+SxQ==",
"length":12753,
"stub":true
}
}
}
Copy the documents content into another one
curl -i -X PUT http://localhost:5984/jug/third_doc -d '{"first_name": "Andy"}'
{"ok":true,"id":"third_doc","rev":"1-16e80e6f62d44c4569d13e2e7a05e373"}
curl -X PUT http://localhost:5984/jug/fourth_doc -d '{"last_name": "Wenk"}'
{"ok":true,"id":"fourth_doc","rev":"1-18236196ad905238b2b24d33a12eb043"}
curl -X COPY http://localhost:5984/jug/third_doc
-H 'destination:fourth_doc?rev=1-18236196ad905238b2b24d33a12eb043'
{"ok":true,"id":"fourth_doc","rev":"2-21431c6bda57d30383987ae2510c309e"}
curl -X COPY http://localhost:5984/jug/third_doc -H 'destination:fifth_doc'
{"ok":true,"id":"fifth_doc","rev":"1-993591377f6cb544ddea933a6ed28e38"}
Copying third_doc to fourth_doc is overwriting not merging!
Copying third_doc to fifth_doc will create the fith_doc newly
Get all documents
curl -X GET http://localhost:5984/jug/_all_docs
{"total_rows":1,"offset":0,"rows":[
{"id":"03cab906fa68e852be833ebb17000ff8","key":"03cab906fa68e852be833ebb17000ff8","value":{"rev":"1-967a00dff5e02add41819138abb3284d"}}
]}
Check also:
Invented by Google
some documents with structure
{
"_id": "f165fc62ed5d14ca84128de1d6034a36",
"_rev": "1-357fda3050771ca747b95c0108a21fe6",
"type": "document_store",
"name": "CouchDB"
}
simplest possible view
{
"_id": "_design/simple",
"_rev": "2-0404067f53ecc72bc660b8bed7576604",
"views": {
"all_database_types": {
"map": "function (doc) { emit(doc.type, doc.name); }"
}
}
}
firing the view
curl -X GET 'http://localhost:5984/map-reduce/_design/simple/ \
_view/all_database_types'
{"total_rows":12,"offset":0,"rows":[
{"id":"f165fc62ed5d14ca84128de1d6036c8c","key":"column_store","value":"BigTable"},
{"id":"f165fc62ed5d14ca84128de1d60375a4","key":"column_store","value":"Hadoop"},
{"id":"f165fc62ed5d14ca84128de1d6037f0e","key":"column_store","value":"Cassandra"},
{"id":"f165fc62ed5d14ca84128de1d6038002","key":"column_store","value":"HBase"},
{"id":"f165fc62ed5d14ca84128de1d6034a36","key":"document_store","value":"CouchDB"},
{"id":"f165fc62ed5d14ca84128de1d6035544","key":"document_store","value":"MongoDB"},
{"id":"f165fc62ed5d14ca84128de1d60358c0","key":"document_store","value":"Riak"},
{"id":"f165fc62ed5d14ca84128de1d60367ac","key":"document_store","value":"Amazon SimpleDB"},
{"id":"f165fc62ed5d14ca84128de1d60387fb","key":"key_value","value":"couchbase"},
{"id":"f165fc62ed5d14ca84128de1d6038f3f","key":"key_value","value":"redis"},
{"id":"f165fc62ed5d14ca84128de1d6039f11","key":"key_value","value":"berkley DB"},
{"id":"f165fc62ed5d14ca84128de1d603a8b6","key":"key_value","value":"Raptor DB"}
]}
attention: start using single quotes for the URL - otherwise cURL will fuck up!
firing the view and receive only data for type=column_store
curl -X GET 'http://localhost:5984/map-reduce/_design/simple/ \
_view/all_database_types?key="document_store"'
{"total_rows":12,"offset":4,"rows":[
{"id":"f165fc62ed5d14ca84128de1d6034a36","key":"document_store","value":"CouchDB"},
{"id":"f165fc62ed5d14ca84128de1d6035544","key":"document_store","value":"MongoDB"},
{"id":"f165fc62ed5d14ca84128de1d60358c0","key":"document_store","value":"Riak"},
{"id":"f165fc62ed5d14ca84128de1d60367ac","key":"document_store","value":"Amazon SimpleDB"}
]}
extending the view with a reduce function
{
"_id": "_design/simple",
"_rev": "2-0404067f53ecc72bc660b8bed7576604",
"views": {
"all_database_types": {
"map": "function (doc) { emit(doc.type, doc.name); }"
"reduce": "_count"
}
}
}
curl -X GET 'http://localhost:5984/map-reduce/_design/simple/ \
_view/all_database_types?group=true'
{"rows":[
{"key":"column_store","value":4},
{"key":"document_store","value":4},
{"key":"key_value","value":4}
]}
If you want to fire the view without reduce, use the parameter reduce=false
See also:
basic _design document structure
{
"_id": "_design/simple",
"_rev": "13-49b3f4710c9b9ecb4bdd9ae8a8ed6c8b",
"views": {
"name": {
"map": "...",
"reduce": "..."
}
},
"shows": {
"name": "..."
},
"lists": {
"name": "..."
},
"language": "javascript"
}
"shows": {
"html": "function(doc, req){log(doc); log(req); if(doc) {return \
'<table><tr><td>id:</td><td>' +doc._id+ \
'</td><tr><tr><td>type:</td><td>'+doc.type+ \
'</td></tr><tr><tr><td>name:</td><td>'+doc.name+ \
'</td></tr><tr><td>last_update:</td><td>'+Date(doc.last_update)+
'</td></tr></table>'} else {return '<h4>Für die angegebene ID' +req.id+ \
' gibt es kein Ergebnis</h4>'}}"
}
curl -X GET http://localhost:5984/map-reduce/_design/simple/_show/ \
html/f165fc62ed5d14ca84128de1d6034a36
<table><tr><td>id:</td><td>f165fc62ed5d14ca84128de1d6034a36</td><tr><tr><td>type:</td><td>document_store</td></tr><tr><tr><td>name:</td><td>CouchDB</td></tr><tr><td>last_update:</td><td>Tue May 08 2012 21:38:03 GMT+0200 (CEST)</td></tr></table>
basic methods
| start() | set options for output - e.g a Header |
| getRow() | content of one document |
| send() | generate the output |
"lists": {
"html": "function(head, req){ \
var row, table = ''; \
start({'headers':{'content-type':'text/html'}}); \
table += \
'<table width=\"300\"><tr><td><b>type:</b></td><td><b>name:</b></td></tr>'; \
while(row=getRow()) { \
table += '<tr><td>' +row.key+ '</td><td>' +row.value+ '</td></tr>'; \
}; \
send(table + '</table>'); \
}"
},
"rewrites": [
{
"from": "/all",
"to": "_list/html/all_database_types",
"method": "GET",
"query": {
"reduce": "false"
}
},
{
"from": "/document_store",
"to": "_list/html/all_database_types",
"method": "GET",
"query": {
"reduce": "false",
"key": "document_store"
}
},
...
],
Results:
http://localhost:5984/map-reduce/_design/simple/_rewrite/allQ.E.D.
Find the configuration files:
couchdb -c
/usr/local/etc/couchdb/default.ini
/usr/local/etc/couchdb/local.ini
[vhosts]
;example.com = /database/
[vhosts]
;example.com = /database/
map-reduce:5984 = /map-reduce/
restart CouchDB
curl -X GET http://map-reduce:5984/
{"db_name":"map-reduce","doc_count":13,"doc_del_count":0,
"update_seq":69,"purge_seq":0,"compact_running":false,
"disk_size":282728,"data_size":5544,
"instance_start_time":"1336516869140172",
"disk_format_version":6,"committed_update_seq":69}
don't forget to set '127.0.0.1 map-reduce' in /etc/hosts!
change local.ini to:
[vhosts]
;example.com = /database/
map-reduce:5984 = /map-reduce/
map-reduce:5984/stats/ = /map-reduce/_design/simple/_rewrite/
now fire http://map-reduce:5984/stats/all