+ All Categories
Home > Technology > CouchDB – A Database for the Web

CouchDB – A Database for the Web

Date post: 29-Jan-2015
Category:
Upload: karel-minarik
View: 114 times
Download: 3 times
Share this document with a friend
Description:
http://webexpo.net/talk/couchdb-database-for-the-web/
Popular Tags:
97
CouchDB — A Database for the Web Karel Minařík
Transcript
Page 1: CouchDB – A Database for the Web

CouchDB — A Database for the WebKarel Minařík

Page 2: CouchDB – A Database for the Web

CouchDB — A Database for the Web

Karel Minařík

→ Independent web designer and developer

→ Ruby, Rails, Git and CouchDB propagandista in .cz

→ Previously: Flash Developer; Art Director; Information Architect;… (see LinkedIn)

→ @karmiq at Twitter

→ karmi.cz

Page 3: CouchDB – A Database for the Web
Page 4: CouchDB – A Database for the Web

CouchDB — A Database for the Web

$ couchdb

Apache CouchDB has started. Time to relax.

Page 5: CouchDB – A Database for the Web

CouchDB — A Database for the Web

Apache CouchDB is a distributed, fault-tolerant

and schema-free document-oriented database

accessible via a RESTful HTTP/JSON API.

http://wiki.apache.org/couchdb

Page 7: CouchDB – A Database for the Web

CouchDB — A Database for the Web

➡ The NoSQL Moniker➡ The CouchDB Story➡ Schema-free Document Storage➡ HTTP From Top to Bottom➡ RESTful API➡ Querying With Map/reduce➡ Fault-tolerant, Distributed, Highly-available and Concurrent➡ Demo: Example Application (Address Book)

Talk Outline

Page 8: CouchDB – A Database for the Web
Page 9: CouchDB – A Database for the Web

Project Voldemort

Page 10: CouchDB – A Database for the Web

CouchDB — A Database for the Web

Reasons for NoSQLNOSQL

NoSQL is neither a “protest movement” nor “trendy bullshit”.

Reasons for developing new databases are real.Most stem from some real pain.

Page 11: CouchDB – A Database for the Web

CouchDB — A Database for the Web

Database denormalization at DiggNOSQL

“Non-relational data stores reverse this model completely, because they don’t have the complex read operations of SQL. The model forces you to shift your computation to the writes, while reducing most reads to simple operations – the equivalent of SELECT * FROM `Table`.“http://about.digg.com/blog/looking-future-cassandra

SELECT `digdate`, `id` FROM `Diggs`WHERE `userid` IN (1, 2, 3, 4, ... 1000000)AND itemid = 123 ORDER BY `digdate` DESC, `id` DESC;

“A full query can actually clock in at 1.5kb, which is many times larger than the actual data we want. With a cold cache, this query can take 14 seconds to execute.”

Page 12: CouchDB – A Database for the Web

CouchDB — A Database for the Web

Redis: Big O Notation Built–InNOSQL

redis> rpush mylist 1

redis> rpush mylist 2

redis> lpop mylist

"1"

...

redis> llen mylist

(integer) 1000000

redis> lpop mylist

"2"

$ redis-benchmark...====== LPOP ======10025 requests completed in 0.53 seconds...93.43% <= 3 milliseconds

Page 13: CouchDB – A Database for the Web

CouchDB — A Database for the Web

Use Case: Job QueueNOSQL

RPUSH

LPOPO(1)

http://github.com/defunkt/resque/blob/master/lib/resque.rb#L133-138

}Millions of items

Page 14: CouchDB – A Database for the Web

CouchDB — A Database for the Web

The CouchDB Story1

Page 15: CouchDB – A Database for the Web

CouchDB — A Database for the Web

Damien Katz: CouchDB and MeTHE COUCHDB STORY

http://www.infoq.com/presentations/katz-couchdb-and-me

Damien Katz(RubyFringe 2008)

Page 16: CouchDB – A Database for the Web

CouchDB — A Database for the Web

Damien Katz: CouchDB and MeTHE COUCHDB STORY

In the beginning, there was C++, XML and custom query language.

Stuff nobody ever got fired for.

Then came Erlang, HTTP, JSON and map/reduce.

Page 17: CouchDB – A Database for the Web

CouchDB — A Database for the Web

Schema–free Documents2

Page 18: CouchDB – A Database for the Web

CouchDB — A Database for the Web

“Relational Data”SCHEMA-FREE STORAGE

OH: “The world is relational!!!”

17 minutes ago via Tweetie for MacRetweeted by 10000 people

Page 19: CouchDB – A Database for the Web

CouchDB — A Database for the Web

That does not mean the world conforms to the third normal form.

Page 20: CouchDB – A Database for the Web

CouchDB — A Database for the Web

In fact, it’s rather the exact opposite.

Page 21: CouchDB – A Database for the Web

CouchDB — A Database for the Web

The Textbook ExampleSCHEMA–FREE DOCUMENTS

Design a customer database.People have names, e-mail, phone numbers, …

How many phone numbers?

Page 22: CouchDB – A Database for the Web

CouchDB — A Database for the Web

The Textbook ExampleSCHEMA–FREE DOCUMENTS

Customers

id INTEGER PNA

first_name VARCHAR

last_name VARCHAR

phone VARCHAR

Now. What about multiple phone numbers?

Relational Databases 101

http://en.wikipedia.org/wiki/First_normal_form#Domains_and_values

Page 23: CouchDB – A Database for the Web

CouchDB — A Database for the Web

The Textbook ExampleSCHEMA–FREE DOCUMENTS

“We will use the database only from the application, anyway.”

Customers

id INTEGER PNA

first_name VARCHAR

last_name VARCHAR

phone VARCHAR

The “solution”, Pt. 1

http://en.wikipedia.org/wiki/First_normal_form#Domains_and_values

Page 24: CouchDB – A Database for the Web

CouchDB — A Database for the Web

The Textbook ExampleSCHEMA–FREE DOCUMENTS

“This is clearly better design!”

Alright. Then, please answer these questions:

• How do you search for a customers given a phone number?• Which customers have the same phone number?• How many phone numbers a customer has?

Then, please add the ability to store four phone numbers. Thanks.

The “solution”, Pt. 2

Customers

id INTEGER PNA

first_name VARCHAR

last_name VARCHAR

phone_1 VARCHAR

phone_2 VARCHAR

phone_3 VARCHAR

http://en.wikipedia.org/wiki/First_normal_form#Domains_and_values

Page 25: CouchDB – A Database for the Web

CouchDB — A Database for the Web

The Textbook ExampleSCHEMA–FREE DOCUMENTS

The Right Solution

Customers

id INTEGER PNAU

first_name VARCHAR

last_name VARCHAR

CustomerPhones

customer_id INTEGER FNi

phone VARCHAR N

http://en.wikipedia.org/wiki/First_normal_form#Domains_and_values

Page 26: CouchDB – A Database for the Web

CouchDB — A Database for the Web

The Textbook ExampleSCHEMA–FREE DOCUMENTS

mysql> SELECT * FROM Customers LEFT JOIN CustomerPhones                               ON Customers.id = CustomerPhones.customer_id;

+‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐+| id | first_name | last_name | customer_id | phone |+‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐+|  1 | John       | Smith     | 1           | 123   | |  1 | John       | Smith     | 1           | 456   | +‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐+

Page 27: CouchDB – A Database for the Web

CouchDB — A Database for the Web

The Textbook ExampleSCHEMA–FREE DOCUMENTS

mysql> SELECT * FROM Customers WHERE id = 1;

+‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐+| id | first_name | last_name |+‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐+|  1 | John       | Smith     | +‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐+

mysql> SELECT phone FROM CustomerPhones WHERE customer_id IN (1);

+‐‐‐‐‐‐‐+| phone |+‐‐‐‐‐‐‐+| 123   | | 456   | +‐‐‐‐‐‐‐+

Page 28: CouchDB – A Database for the Web

CouchDB — A Database for the Web

Structured dataSCHEMA–FREE DOCUMENTS

But, damn!, I want something like this:

{  "id"         : 1,

  "first_name" : "Clara",  "last_name"  : "Rice",

  "phones"     : ["0000 777 888 999", "0000 123 456 789", "0000 314 181 116"]}

“No problem, you just iterate over the rows and build your object. That’s the way it is!”

“If this would be too painful, we will put some cache there.”

Page 29: CouchDB – A Database for the Web

CouchDB — A Database for the Web

Ephemeral dataSCHEMA–FREE DOCUMENTS

class User < ActiveRecord::Base

  serialize :preferences

end

Not everything needs to be done “right”. Right?

Page 30: CouchDB – A Database for the Web

CouchDB — A Database for the Web

“Consistency”SCHEMA–FREE DOCUMENTS

Does the “Right Way“ sometimes fail?Hell yeah.

EXAMPLE

When designing an invoicing application, you store the customer for the invoice the “right way”, via foreign keys.

Then, the customer address changes.

Did the address on the invoice also changed?

Page 31: CouchDB – A Database for the Web

CouchDB — A Database for the Web

cityreality, ltd.

123 EVERYWHERE AVENUE CITY, ST 00000

Phone: 555.555.5555

Fax: 444.444.4444

Skype: city.reality.ltd

Documents in the Real WorldSCHEMA–FREE DOCUMENTS

1 2 3 F a c t o r y S t r e e t C i t y , S t 0 0 0 0 0

design things

UNDERGROUND RECORDS

[email protected]

F: 555.555.5555

P: 555.555.5555M: 777.777.7777M: 888.000.1111

123 BOULEVARDAVE, SUITE 000LOS ANGELES, U.S.A/

www.undergroundrecor

ds.com

http://guide.couchdb.org/draft/why.html#better

Page 32: CouchDB – A Database for the Web

CouchDB — A Database for the Web

Documents in the Real WorldSCHEMA–FREE DOCUMENTS

{ "_id" : "clara-rice", "_rev" : "1-def456",

"first_name" : "Clara", "last_name" : "Rice",

"phones" : { "mobile" : "0000 777 888 999" "home" : "0000 123 456 789", "work" : "0000 314 181 116" },

"addresses" : { "home" : { "street" : "Wintheiser Ports", "number" : "789/23", "city" : "Erinshire", "country" : "United Kingdom" }, },

"occupation" : "model", "birthday" : "1970/05/01",

"groups" : ["friends", "models"],

"created_at" : "2010/01/01 10:00:00 +0000"}

JSON

Page 33: CouchDB – A Database for the Web

CouchDB — A Database for the Web

Documents in the Real WorldSCHEMA–FREE DOCUMENTS

Page 34: CouchDB – A Database for the Web

CouchDB — A Database for the Web

Procrustean Bed

Page 35: CouchDB – A Database for the Web

CouchDB — A Database for the Web

RESTful HTTP3

Page 36: CouchDB – A Database for the Web

1990s

Page 37: CouchDB – A Database for the Web

CouchDB — A Database for the Web

Django may be built for the Web,but CouchDB is built of the Web.

I’ve never seen soware that so completely embraces the philosophies behind HTTP.Jacob Kaplan-Moss, Of the Web (2007)

http://jacobian.org/writing/of-the-web/

HTTP

Built “Of the Web”

Page 38: CouchDB – A Database for the Web

CouchDB — A Database for the Web

CouchDB makes Django look old-school in the same way that Django makes ASP look outdated.

HTTP

Built “Of the Web”

http://jacobian.org/writing/of-the-web/

Page 39: CouchDB – A Database for the Web

CouchDB — A Database for the Web

HTTP is the lingua anca of our age; if you speak HTTP, it opens up all sorts of doors.

ere’s something almost subversive about CouchDB; it’s completely language-, platform-, and OS-agnostic.

Built “Of the Web”HTTP

http://jacobian.org/writing/of-the-web/

Page 40: CouchDB – A Database for the Web

CouchDB — A Database for the Web

HOST=http://localhost:5984

curl ‐X GET $HOST# {"couchdb":"Welcome","version":"0.11.0b22c551bb‐git"}

curl ‐X GET $HOST/my‐database# {"error":"not_found","reason":"no_db_file"}

curl ‐X PUT $HOST/my‐database# {"ok":true}

curl ‐X PUT $HOST/my‐database/abc123 ‐d '{"foo":"bar"}'# {"ok":true,"id":"abc123","rev":"1‐4c6114c65e295552ab1019e2b046b10e"}

curl ‐X GET $HOST/my‐database/abc123# {"_id":"abc123","_rev":"1‐4c6114c65e295552ab1019e2b046b10e","foo":"bar"}

curl ‐X DELETE $HOST/my‐database/abc123?rev=2‐d179f665eb01834faf192153dc72dcb3# {"ok":true,"id":"abc123","rev":"1‐4c6114c65e295552ab1019e2b046b10e"}

HTTP APIHTTP

Page 41: CouchDB – A Database for the Web

CouchDB — A Database for the Web

require 'rubygems'require 'ostruct'

require 'restclient'

require 'json'

class Article < OpenStruct

  def self.db(path='')    RestClient::Resource.new "http://localhost:5984/blog/#{path}",                             :headers => { :content_type => :json, :accept => :json }  end

  db.put '' rescue RestClient::PreconditionFailed

  def self.create(params={})    new db.post(params.to_json)  end

  def self.find(id)    new JSON.parse( db(id).get )  end

  def destroy    self.class.db(self._id + "?rev=#{self._rev}").delete  end end

Easy To WrapHTTP

HTTP libraryJSON library

12

Page 42: CouchDB – A Database for the Web

CouchDB — A Database for the Web

Article.create :_id   => 'my‐first‐post',               :title => 'CouchDB is easy',               :body  => 'So relax!',               :tags  => ['couchdb', 'databases'] rescue RestClient::Conflict

article =  Article.find('my‐first‐post')

puts "Got an article:"p article

puts "\n‐‐‐‐‐‐"puts "Title: %s" % article.title        + "     (class: #{article.title.class})"puts "Tags:  %s" % article.tags.inspect + "     (class: #{article.tags.class})"puts "‐‐‐‐‐‐\n\n"

puts "Deleting article..."article.destroy

Easy To WrapHTTP

Page 43: CouchDB – A Database for the Web

CouchDB — A Database for the Web

$ curl ‐X POST http://localhost:5984/_replicate \       ‐d '{"source":"database",             "target":"http://example.org/database"}'

HTTP from Top to BottomHTTP

Page 44: CouchDB – A Database for the Web

CouchDB — A Database for the Web

$ curl ‐i ‐X GET $HOST/my‐database/abc123

HTTP/1.1 200 OKServer: CouchDB/1.0.1 (Erlang OTP/R14B)Etag: "4‐f04f2435e031054d6b5298c5841ae052"Date: Thu, 23 Sep 2010 12:56:37 GMTContent‐Type: text/plain;charset=utf‐8Content‐Length: 73Cache‐Control: must‐revalidate

{"_id":"abc123","_rev":"4‐f04f2435e031054d6b5298c5841ae052","foo":"bar"}

Making Real Use of HTTPHTTP

Page 45: CouchDB – A Database for the Web

$ cat /etc/squid3/squid.conf

cache_peer 192.168.100.2 parent 5984 0 no‐query originserver name=masteracl master_acl method GET POST PUT DELETEcache_peer_access master allow master_acl

Page 46: CouchDB – A Database for the Web

CouchDB — A Database for the Web

REST is a set of principles that define how Web standards, such as HTTP and URIs, are supposed to be used. (...) In summary, the five key principles are:

➡ Give every “thing” an ID➡ Link things together➡ Use standard methods➡ Resources with multiple representations➡ Communicate statelessly

Stefan Tilkov, A Brief Introduction to REST

What is “RESTful”?HTTP

http://www.infoq.com/articles/rest-introduction

Page 47: CouchDB – A Database for the Web

CouchDB — A Database for the Web

What is “RESTful”?HTTP

The basic idea is even more simple, though.

HTTP is not just a “transfer protocol”.

It is the interface for interacting with “things” itself.

Page 48: CouchDB – A Database for the Web

CouchDB — A Database for the Web

Fault-Tolerant and Concurrent4

Page 49: CouchDB – A Database for the Web

CouchDB — A Database for the Web

$ kill ‐9 <PID>

CouchDB has no off switch.CouchDB has no repair command.

Page 50: CouchDB – A Database for the Web

CouchDB — A Database for the Webhttp://www.youtube.com/watch?v=uKfKtXYLG78

Erlang!

ErlangFAULT–TOLERANT

Page 51: CouchDB – A Database for the Web

CouchDB — A Database for the Web

Erlang's main strength is support for concurrency. It has a small but powerful set of primitives to create processes and communicate among them.(…) a benchmark with 20 million processes has been successfully performed.

ErlangFAULT–TOLERANT

http://en.wikipedia.org/wiki/Erlang_(programming_language)

Page 52: CouchDB – A Database for the Web

CouchDB — A Database for the Webhttp://guide.couchdb.org/draft/btree.html

Append–Only B–TreeFAULT–TOLERANT

Page 53: CouchDB – A Database for the Web

CouchDB — A Database for the Web

Querying With Map/reduce5

Page 54: CouchDB – A Database for the Web

CouchDB — A Database for the Web

The Google PaperMAP/REDUCE

http://labs.google.com/papers/mapreduce.html

Page 55: CouchDB – A Database for the Web

CouchDB — A Database for the Web

The ConceptMAP/REDUCE

module Enumerable  alias :reduce :inject unless method_defined? :reduceend

(1..3).map    { |number| number * 2 }# => [2, 4, 6]

(1..3).reduce(0) { |sum, number| sum += number}# => 6

Page 56: CouchDB – A Database for the Web

CouchDB — A Database for the Web

function(doc) {  if (doc.last_name && doc.first_name) {    emit( doc.last_name + ' ' + doc.first_name, doc )  }}

The Simplest ViewMAP/REDUCE

Page 57: CouchDB – A Database for the Web

CouchDB — A Database for the Web

function(doc) {  if (doc.last_name && doc.first_name) {    emit( doc.last_name + ' ' + doc.first_name, doc )  }}

The Simplest ViewMAP/REDUCE

INPUT

OUTPUT KEY VALUE

Page 58: CouchDB – A Database for the Web

CouchDB — A Database for the Web

The Result of MapMAP/REDUCE

Key Value

"Armstrong Lottie"

_id: "lottie‐armstrong",_rev: "2‐fcb71b26096957b3ff3ffd2970f3c933",addresses: {  home: {  city: "Murphyville"  ...  }},first_name: "Lottie",last_name: "Armstrong",occupation: "programmer",

"Bailey Kaelyn"

_id: "kaelyn‐bailey",_rev: "1‐2e25e6c9448520fa796988894423a23b",addresses: {      home: {        city: "Lake Dedric"        ...      }},first_name: "Kaelyn",last_name: "Bailey",occupation: "supermodel"

... ...

Page 59: CouchDB – A Database for the Web

CouchDB — A Database for the Web

The Result of MapMAP/REDUCE

Page 60: CouchDB – A Database for the Web

CouchDB — A Database for the Web

function(doc) { emit(doc.occupation, 1);}

Even Simpler ViewMAP/REDUCE

Page 61: CouchDB – A Database for the Web

CouchDB — A Database for the Web

Result of Even Simpler ViewMAP/REDUCE

http://localhost:5984/_utils/database.html?addressbook/_design/person/_view/by_occupation

Page 62: CouchDB – A Database for the Web

CouchDB — A Database for the Web

function(keys, values) {  return sum(values)}

A Simple ReduceMAP/REDUCE

Page 63: CouchDB – A Database for the Web

CouchDB — A Database for the Web

Result of a Simple ReduceMAP/REDUCE

http://localhost:5984/_utils/database.html?addressbook/_design/person/_view/by_occupation

Page 64: CouchDB – A Database for the Web

CouchDB — A Database for the Web

Built–In Erlang Reduce functionsMAP/REDUCE

http://wiki.apache.org/couchdb/Built-In_Reduce_Functions#Available_Build-In_Functions

_count_sum_stats

$ couchdb

Apache CouchDB has started. Time to relax.

Page 65: CouchDB – A Database for the Web

CouchDB — A Database for the Web

function(doc) {  for (group in doc.groups) {    emit(doc.groups[group], 1)  }}

_count

Map/Reduce for Counting “tag-like stuff”MAP/REDUCE

Page 66: CouchDB – A Database for the Web

CouchDB — A Database for the Web

Result of the Map phaseMAP/REDUCE

http://localhost:5984/_utils/database.html?addressbook/_design/person/_view/by_groups

Page 67: CouchDB – A Database for the Web

CouchDB — A Database for the Web

Result of the Reduce PhaseMAP/REDUCE

http://localhost:5984/_utils/database.html?addressbook/_design/person/_view/by_groups

Page 68: CouchDB – A Database for the Web

CouchDB — A Database for the Web

function(doc) {  var date = new Date(doc.birthday)  emit( [date.getFullYear(), date.getMonth()+1, date.getDate()], 1 )}

_count

Group LevelsMAP/REDUCE

COMPOSITE KEY (ARRAY)

Page 69: CouchDB – A Database for the Web

CouchDB — A Database for the Web

Group Level ExactMAP/REDUCE

http://localhost:5984/_utils/database.html?addressbook/_design/person/_view/by_birthday

Page 70: CouchDB – A Database for the Web

CouchDB — A Database for the Web

Group Level 2MAP/REDUCE

http://localhost:5984/_utils/database.html?addressbook/_design/person/_view/by_birthday

Page 71: CouchDB – A Database for the Web

CouchDB — A Database for the Web

Group Level 1MAP/REDUCE

http://localhost:5984/_utils/database.html?addressbook/_design/person/_view/by_birthday

Page 72: CouchDB – A Database for the Web

CouchDB — A Database for the Web

key

startkey

startkey_docid

endkey

endkey_docid

limit

stale

descending

skip

group

group_level

reduce

include_docs

Parameters for querying viewsQUERYING VIEWS

Page 73: CouchDB – A Database for the Web

CouchDB — A Database for the Web

A Complex Map/ReduceQUERYING VIEWS

Page 74: CouchDB – A Database for the Web

CouchDB — A Database for the Web

A Complex Map/ReduceQUERYING VIEWS

SELECT

      COUNT(*) AS count,        DATE_FORMAT(published_at, "%Y/%m/%d") AS date,

        keywords.value AS keyword      FROM feed_entries        INNER JOIN feeds ON feed_entries.feed_id = feeds.id

        INNER JOIN keywords ON feeds.keyword_id = keywords.id      WHERE DATE_SUB(CURDATE(), INTERVAL 90 DAY) <= feed_entries.published_at

      GROUP BY date, keyword      ORDER BY date, keyword ASC;

Page 75: CouchDB – A Database for the Web

CouchDB — A Database for the Web

A Complex Map/ReduceQUERYING VIEWS

Streamgraph.load_data({  max : 170,

  keywords : ['ruby', 'python', 'erlang', 'javascript', 'haskell'],

  values   : [    { date: '2010/01/01', ruby: 50,  python: 20, erlang: 5,  javascript: 30, haskell: 50 },    { date: '2010/02/01', ruby: 20,  python: 20, erlang: 2,  javascript: 40, haskell: 43 },    { date: '2010/03/01', ruby: 70,  python: 20, erlang: 10, javascript: 80, haskell: 15 },    { date: '2010/04/01', ruby: 20,  python: 40, erlang: 8,  javascript: 30, haskell: 12 },    { date: '2010/05/01', ruby: 150, python: 30, erlang: 12, javascript: 40, haskell: 18 },    { date: '2010/06/01', ruby: 30, python: 10, erlang: 14, javascript: 170, haskell: 14 }  ]

});

But. We don’t need a table. We need the data in a format like this:

Page 76: CouchDB – A Database for the Web

CouchDB — A Database for the Web

The Map PhaseQUERYING VIEWS

function(doc) {  var fix_date = function(junk) {      var formatted = junk.toString().replace(/‐/g,"/").replace("T"," ").substring(0,19);      return new Date(formatted);    };  // Format integers to have at least two digits.  var f = function(n) { return n < 10 ? '0' + n : n; }  // This is a format that collates in order and tends to work with  // JavaScript's new Date(string) date parsing capabilities, unlike rfc3339.  Date.prototype.toJSON = function() {      return this.getUTCFullYear()   + '/' +           f(this.getUTCMonth() + 1) + '/' +           f(this.getUTCDate())      + ' ' +           f(this.getUTCHours())     + ':' +           f(this.getUTCMinutes())   + ':' +           f(this.getUTCSeconds())   + ' +0000';  };  if (doc['couchrest‐type'] == 'Mention') {    for ( keyword in doc.keywords ) {      var key = fix_date(doc.published_at).toJSON().substring(0,10);      var value = {};      value[ doc.keywords[keyword] ] = 1;      emit( key, value);    }  }}

Page 77: CouchDB – A Database for the Web

CouchDB — A Database for the Web

The Reduce PhaseQUERYING VIEWS

function(keys, values, rereduce) {  if (rereduce) {    var result = {}    for ( item in values ) {      for (prop in values[item]) {        if ( result[prop] ) { result[prop] += values[item][prop]  }        else { result[prop] = values[item][prop]  }      }    }    return result;  }  else {    // Prepare the data for the re‐reduce    var date   = keys[0][0];    var result = {}    for (value in values) {      var item = values[value];      for (prop in item) {        if ( result[prop] ) { result[prop] += item[prop] }        else { result[prop] = item[prop] }      }    }    return result;  }}

Page 78: CouchDB – A Database for the Web

CouchDB — A Database for the Web

The ResultQUERYING VIEWS

{    "rows": [        {            "key": "2010/09/22",            "value": { "ruby": 8, "python": 19 }        },        {            "key": "2010/09/23",            "value": { "ruby": 24, "python": 12 }         },        {            "key": "2010/09/24",            "value": { "ruby": 7, "python": 8 }        }    ]}

$ curl http://localhost:5984/customer_database/_design/Mention/_view/by_date_and_keyword?group=true

Page 79: CouchDB – A Database for the Web

CouchDB — A Database for the Web

I ♥JS. Or... don’t?QUERYING VIEWS

Page 80: CouchDB – A Database for the Web

CouchDB — A Database for the Web

Complex QueriesQUERYING VIEWS

So… What if you need something like:

Show me all supermodels who live in Beckerborough.

Out of luck?

Page 81: CouchDB – A Database for the Web

CouchDB — A Database for the Web

CouchDB–LuceneCOMPLEX QUERIES

Show me all supermodels who live in Beckerborough.

This guy knows.

Page 82: CouchDB – A Database for the Web

CouchDB — A Database for the Webhttp://github.com/rnewson/couchdb-lucene

Couchdb-Lucene.When you need foo AND bar.

foo AND barCOMPLEX QUERIES

Page 83: CouchDB – A Database for the Web

CouchDB — A Database for the Web

function(doc) {

  var result = new Document();

  if (doc.occupation)     {    result.add(doc.occupation,                    {"field":"occupation"})  }

  if (doc.addresses)       {    for (address in doc.addresses) {      result.add(doc.addresses[address].city,     {"field":"city"})    }  }

  return result;

}

Indexing functionCOUCHDB-LUCENE

http://localhost:5984/addressbook/_fti/_design/person/search?q=occupation:supermodel AND city:Beckerborough

Page 84: CouchDB – A Database for the Web

CouchDB — A Database for the Web

Distributed6

Page 85: CouchDB – A Database for the Web

CouchDB — A Database for the Web

Ubuntu OneDISTRIBUTED

Page 86: CouchDB – A Database for the Web

CouchDB — A Database for the Web

ReplicationDISTRIBUTED

Page 87: CouchDB – A Database for the Web

CouchDB — A Database for the Web

Conflict ResolutionsDISTRIBUTED

http://guide.couchdb.org/draft/consistency.html#study

_rev1

Page 88: CouchDB – A Database for the Web

CouchDB — A Database for the Webhttp://ephemera.karmi.cz/post/247255194/simple-couchdb-multi-master-clustering-via-nginx

Simple Clustering With HTTP Reverse ProxiesDISTRIBUTED

Page 89: CouchDB – A Database for the Web

CouchDB — A Database for the Web

Scaling DownDISTRIBUTED

http://www.couchone.com/page/android

Page 90: CouchDB – A Database for the Web

CouchDB — A Database for the Web

CouchAppsDISTRIBUTED

Page 91: CouchDB – A Database for the Web

CouchDB — A Database for the Web

CouchAppsDISTRIBUTED

http://pollen.nymphormation.org/afgwar/_design/afgwardiary/index.html

Page 92: CouchDB – A Database for the Web

CouchDB — A Database for the Web

CouchAppsDISTRIBUTED

Page 93: CouchDB – A Database for the Web

CouchDB — A Database for the Web

Resources7

Page 94: CouchDB – A Database for the Web

CouchDB — A Database for the Web

ResourcesDISTRIBUTED

➡ http://guide.couchdb.org

➡ https://nosqleast.com/2009/#speaker/miller

➡ http://www.couchone.com/migrating-to-couchdb

➡ http://wiki.apache.org/couchdb/

➡ http://blog.couchone.com/

➡ http://stackoverflow.com/tags/couchdb/

Page 95: CouchDB – A Database for the Web

CouchDB — A Database for the Web

Demo: Example Application8

Page 96: CouchDB – A Database for the Web

CouchDB — A Database for the Web

ApplicationDEMO

http://karmi.couchone.com/addressbook/_design/person/_list/all/all

SOURCE CODE: http://github.com/karmi/couchdb-showcase

Page 97: CouchDB – A Database for the Web

Questions!


Recommended