Couchdb has REST APIs and it works well with curl.
Let’s build a contact database in Futon with following:
Documents
{"_id": "bill", "name": "bill", "groups": ["friends"], "type": "contact"}
{"_id": "john", "name": "john", "groups": ["friends", "coworkers"], "type": "contact"}
{"_id": "111-222-3333", "phone": "home", "contact_id": "bill", "type": "phone"}
{"_id": "222-333-4444", "phone": "mobile", "contact_id": "bill", "type": "phone"}
{"_id": "333-444-5555", "phone": "mobile", "contact_id": "john", "type": "phone"}
{"_id": "444-555-6666", "phone": "work", "contact_id": "john", "type": "phone"}
{"_id": "friends", "desc": "friends group", "type": "group"}
{"_id": "coworkers", "desc": "friends group", "type": "group"}
{"_id": "john", "name": "john", "groups": ["friends", "coworkers"], "type": "contact"}
{"_id": "111-222-3333", "phone": "home", "contact_id": "bill", "type": "phone"}
{"_id": "222-333-4444", "phone": "mobile", "contact_id": "bill", "type": "phone"}
{"_id": "333-444-5555", "phone": "mobile", "contact_id": "john", "type": "phone"}
{"_id": "444-555-6666", "phone": "work", "contact_id": "john", "type": "phone"}
{"_id": "friends", "desc": "friends group", "type": "group"}
{"_id": "coworkers", "desc": "friends group", "type": "group"}
Views
{
"_id": "_design/contacts",
"_rev": "12-d069646c5b9ff9caf55c1fa89e3f7ea4",
"language": "javascript",
"views": {
"group_members": {
"map": "function(doc) {
if (doc.type == 'contact') {
for(var i in doc.groups) {
emit([doc.groups[i],0], null);
}
} else if (doc.type == 'group') {
emit([doc._id,1], null);
}
}"
},
"details": {
"map": "function(doc) {
if (doc.type == 'contact') {
emit([doc._id,0], null);
}
else if (doc.type == 'phone') {
emit([doc.contact_id, 1], doc.phoneType);
}
}"
}
}
}
"_id": "_design/contacts",
"_rev": "12-d069646c5b9ff9caf55c1fa89e3f7ea4",
"language": "javascript",
"views": {
"group_members": {
"map": "function(doc) {
if (doc.type == 'contact') {
for(var i in doc.groups) {
emit([doc.groups[i],0], null);
}
} else if (doc.type == 'group') {
emit([doc._id,1], null);
}
}"
},
"details": {
"map": "function(doc) {
if (doc.type == 'contact') {
emit([doc._id,0], null);
}
else if (doc.type == 'phone') {
emit([doc.contact_id, 1], doc.phoneType);
}
}"
}
}
}
Let’s query for all members of the friends group. Notice the key is an array.
$ curl 'http://localhost:5984/contacts/_design/contacts/_view/group_members?startkey=\["friends"\]&endkey=\["friends"\{\}\]'
Results
{"total_rows":5,"offset":2,"rows":[
{"id":"bill","key":["friends",0],"value":null},
{"id":"john","key":["friends",0],"value":null},
{"id":"friends","key":["friends",1],"value":null}
]}
{"id":"bill","key":["friends",0],"value":null},
{"id":"john","key":["friends",0],"value":null},
{"id":"friends","key":["friends",1],"value":null}
]}
Let’s query for all members of the friends group with include_docs=true.
$ curl 'http://localhost:5984/contacts/_design/contacts/_view/group_members?startkey=\["friends"\]&endkey=\["friends"\{\}\]&include_docs=true'
Results
{"total_rows":5,"offset":2,"rows":[
{"id":"bill","key":["friends",0],"value":null,"doc":{"_id":"bill","_rev":"1-8358d8caf24c130a9c7ce6994c05abf7","name":"bill","groups":["friends"],"type":"contact"}},
{"id":"john","key":["friends",0],"value":null,"doc":{"_id":"john","_rev":"1-4f66287ab931de7591eb83cbd924dead","name":"john","groups":["friends","coworkers"],"type":"contact"}},
{"id":"friends","key":["friends",1],"value":null,"doc":{"_id":"friends","_rev":"1-276a9b9789261919c80dd3cf147aa93e","desc":"friends group","type":"group"}}
]}
{"id":"bill","key":["friends",0],"value":null,"doc":{"_id":"bill","_rev":"1-8358d8caf24c130a9c7ce6994c05abf7","name":"bill","groups":["friends"],"type":"contact"}},
{"id":"john","key":["friends",0],"value":null,"doc":{"_id":"john","_rev":"1-4f66287ab931de7591eb83cbd924dead","name":"john","groups":["friends","coworkers"],"type":"contact"}},
{"id":"friends","key":["friends",1],"value":null,"doc":{"_id":"friends","_rev":"1-276a9b9789261919c80dd3cf147aa93e","desc":"friends group","type":"group"}}
]}
Let’s get Bill’s contact details.
$ curl -v 'http://localhost:5984/contacts/_design/contacts/_view/details?startkey=\["bill"\]&endkey=\["bill",\{\}\]&include_docs=false'
Results
{"total_rows":6,"offset":0,"rows":[
{"id":"bill","key":["bill",0],"value":null},
{"id":"111-222-3333","key":["bill",1],"value":null},
{"id":"222-333-4444","key":["bill",1],"value":null}
]}
{"id":"bill","key":["bill",0],"value":null},
{"id":"111-222-3333","key":["bill",1],"value":null},
{"id":"222-333-4444","key":["bill",1],"value":null}
]}
Bill’s contact details with include_docs=true
$ curl -v 'http://localhost:5984/contacts/_design/contacts/_view/details?startkey=\["bill"\]&endkey=\["bill",\{\}\]&include_docs=true'
Results
{"total_rows":6,"offset":0,"rows":[
{"id":"bill","key":["bill",0],"value":null,"doc":{"_id":"bill","_rev":"1-8358d8caf24c130a9c7ce6994c05abf7","name":"bill","groups":["friends"],"type":"contact"}},
{"id":"111-222-3333","key":["bill",1],"value":null,"doc":{"_id":"111-222-3333","_rev":"1-5fc019b84d86073895fd126bdc3f373f","phone":"home","contact_id":"bill","type":"phone"}},
{"id":"222-333-4444","key":["bill",1],"value":null,"doc":{"_id":"222-333-4444","_rev":"1-730af0703a373ca2e29d793548c79d62","phone":"mobile","contact_id":"bill","type":"phone"}}
]}
{"id":"bill","key":["bill",0],"value":null,"doc":{"_id":"bill","_rev":"1-8358d8caf24c130a9c7ce6994c05abf7","name":"bill","groups":["friends"],"type":"contact"}},
{"id":"111-222-3333","key":["bill",1],"value":null,"doc":{"_id":"111-222-3333","_rev":"1-5fc019b84d86073895fd126bdc3f373f","phone":"home","contact_id":"bill","type":"phone"}},
{"id":"222-333-4444","key":["bill",1],"value":null,"doc":{"_id":"222-333-4444","_rev":"1-730af0703a373ca2e29d793548c79d62","phone":"mobile","contact_id":"bill","type":"phone"}}
]}