SlideShare a Scribd company logo
1 of 91
Real World



     John Wood
 Windy City DB 2011
   @johnpwood
About Me
• Software Developer at Signal
• Coding for about 15 years
• Working with CouchDB for 2.5 years (in
  production for about 2 years)

• Enjoy tinkering with data storage solutions
CouchDB Overview
Document Database
{
    “_id” : “2d7f015226a05b6940984bbe39004fde”,
    “_rev” : “2-477f6ab2dec6df185de1a078d270d8”,
    “first_name” : “John”,
    “last_name” : “Wood”,
    “interests” : [“hacking”, “fishing”, “reading”],
    “offspring” : [
                    { “name” : “Dylan”, “age” : 6 },
                    { “name” : “Chloe”, “age” : 3 }
                  ]
}
Strong Focus on
   Replication
RESTful API
# Create
POST http://localhost:5984/employees

# Read
GET http://localhost:5984/employees/1

# Update
PUT http://localhost:5984/employees/1

# Delete
DELETE http://localhost:5984/employees/1
Queried and Indexed
  with MapReduce
 function(doc) {
   if (doc.first_name == “John”)
     emit(doc._id, 1);
 }


function(keys, values, rereduce) {
  return sum(values);
}
Ultra Durable
Erlang OTP
Views
MapReduce

// Map
function(doc) {
  emit(doc._id, 1);
}

// Reduce
function(keys, values, rereduce) {
  return sum(values);
}
MapReduce
// Map
function(doc) {
  if (doc.dependents) {
    for (i in doc.dependents) {
       emit(doc._id, doc.dependents[i]);
    }
  }
}

// Reduce
_count
MapReduce
function(keys, values, rereduce) {
  function sum(type_counts, totals, status) {
    if (type_counts[status]) { // OK or ERR
      if (!totals[status]) {
        totals[status] = new Object();
      }
      var status_totals = totals[status];
      var status_type_counts = type_counts[status];
      for (key in status_type_counts) { // MO, MT, CM, etc.
        var count = status_type_counts[key];
        if (!status_totals[key]) {
          status_totals[key] = count;
        } else {
          status_totals[key] += count;
        }
      }
    }
  }
  var totals = new Object();
  // values should be something like
  // {"OK":{"MO":1234,"MT":1000,"CM":20},"ERR":{"MO":1,"MT": 1}}
  for (i = 0; i < values.length; i++) {
    var message_count = values[i];
    sum(message_count, totals, 'OK');
  }
  return totals;
}
Design Documents
{
  "_id": "_design/stats",
  "views": {
    "total_employees": {
       "map": "function(doc) { emit(doc._id, 1); }",
       "reduce": "function(keys, values, rereduce) { return
sum(values); }"
    },
    "by_lastname": {
       "map": "function(doc) { emit(doc.last_name, null); }"
    },
    "dependents": {
       "map": "function(doc) { if (doc.dependents) { for (i in
doc.dependents) { emit(doc._id, doc.dependents[i]); } } }",
       "reduce": "_count"
    }
  }
}
{
    "_id": "1",
    "first_name": "Robert",                                                                                                       {
    "last_name": "Johnson",                                                                                                          "_id": "4",
    "date_hired": "2010/01/10",                                                                                                      "first_name": "Bob",
    "dependents": [                                          {                                 {                                     "last_name": "Smith",
       { "first_name": "Margie", "last_name": "Johnson" },        "_id": "2",                       "_id": "3",                       "salary": 80000,
       { "first_name": "Charlie", "last_name": "Johnson" },       "first_name": "Jim",               "first_name": "Sally",             "date_hired": "2010/03/11",
       { "first_name": "Sophie", "last_name": "Johnson" }         "last_name": "Jones",             "last_name": "Stevenson",         "dependents": [
    ],                                                           "date_hired": "2010/02/11",       "date_hired": "2010/04/23",          { "first_name": "Susan", "last_name": "Smith" }
    "salary": 250000                                             "salary": 150000                  "salary": 100000                  ]
}                                                            }                                 }                                 }




                                                             MapReduce

      {"total_rows":4,"offset":0,"rows":[
      {"id":"1","key":"1","value":{"first_name":"Margie","last_name":"Johnson"}},
      {"id":"1","key":"1","value":{"first_name":"Charlie","last_name":"Johnson"}},
      {"id":"1","key":"1","value":{"first_name":"Sophie","last_name":"Johnson"}},
      {"id":"4","key":"4","value":{"first_name":"Susan","last_name":"Smith"}}
      ]}
{
    "_id": "1",
    "first_name": "Robert",                                                                                                       {
    "last_name": "Johnson",                                                                                                          "_id": "4",
    "date_hired": "2010/01/10",                                                                                                      "first_name": "Bob",
    "dependents": [                                          {                                 {                                     "last_name": "Smith",
       { "first_name": "Margie", "last_name": "Johnson" },        "_id": "2",                       "_id": "3",                       "salary": 80000,
       { "first_name": "Charlie", "last_name": "Johnson" },       "first_name": "Jim",               "first_name": "Sally",             "date_hired": "2010/03/11",
       { "first_name": "Sophie", "last_name": "Johnson" }         "last_name": "Jones",             "last_name": "Stevenson",         "dependents": [
    ],                                                           "date_hired": "2010/02/11",       "date_hired": "2010/04/23",          { "first_name": "Susan", "last_name": "Smith" }
    "salary": 250000                                             "salary": 150000                  "salary": 100000                  ]
}                                                            }                                 }                                 }




                                                             MapReduce

                                                                     {"rows":[
                                                                     {"key":null,"value":4}
                                                                     ]}
{
    "_id": "1",
    "first_name": "Robert",                                                                                                       {
    "last_name": "Johnson",                                                                                                          "_id": "4",
    "date_hired": "2010/01/10",                                                                                                      "first_name": "Bob",
    "dependents": [                                          {                                 {                                     "last_name": "Smith",
       { "first_name": "Margie", "last_name": "Johnson" },        "_id": "2",                       "_id": "3",                       "salary": 80000,
       { "first_name": "Charlie", "last_name": "Johnson" },       "first_name": "Jim",               "first_name": "Sally",             "date_hired": "2010/03/11",
       { "first_name": "Sophie", "last_name": "Johnson" }         "last_name": "Jones",             "last_name": "Stevenson",         "dependents": [
    ],                                                           "date_hired": "2010/02/11",       "date_hired": "2010/04/23",          { "first_name": "Susan", "last_name": "Smith" }
    "salary": 250000                                             "salary": 150000                  "salary": 100000                  ]
}                                                            }                                 }                                 }




                                                             MapReduce

                                                                     {"rows":[
                                                                     {"key":"1","value":3},
                                                                     {"key":"4","value":1}
                                                                     ]}
View Structure




  http://guide.couchdb.org/editions/1/en/views.html
View Structure
               ?key="ch"




  http://guide.couchdb.org/editions/1/en/views.html
Real World Example
The Problem
•   Reports that utilized data in some large tables (30M+
    rows) were taking a very long to create

    •   Increasing query execution times

    •   Occasional page timeouts

•   Limited resources for super powered hardware or the
    leading relational database product

•   Database migrations on these large tables were taking an
    increasingly long time to run
The Solution
•   Using CouchDB as an archive database

•   Migrated old data in tables to CouchDB, dramatically
    reducing the tables sizes, speeding up queries that were
    still hitting those tables

•   Re-wrote SQL queries as views to fetch data from the
    archive database, dramatically reducing the amount of
    time needed to fetch the old data

•   Views updated nightly with the new set of archived data
Replication
POST /_replicate
{"source":"database",
 "target":"http://example.org/database"}
Unidirectional
Bidirectional
Continuous
Filtered



function(doc, req) {
  if (doc.type && doc.type == "foo") {
    return true;
  } else {
    return false;
  }
}
Filtered



function(doc, req) {
  if (doc.type && doc.type == req.query.doc_type) {
    return true;
  } else {
    return false;
  }
}
Named
Conflicts
"_conflicts":
["2-7c971bb974251ae8541b8fe045964219"]
Finding Conflicts
     function(doc) {
       if (doc._conflicts) {
         emit(doc._conflicts, null);
       }
     }

{"total_rows":1,"offset":0,"rows":[
{"id":"foo","key":
["2-7c971bb974251ae8541b8fe045964219"],"value":null}
]}
                 http://guide.couchdb.org/draft/conflicts.html
Resolving Conflicts

# Step 1
PUT /db/document {... merged data ...}

# Step 2
DELETE /db/document?
rev=2-7c971bb974251ae8541b8fe045964219
Real World Example




    http://www.couchbase.com/case-studies/bbc
The Problem
•   Need to make sure site was always up and available, even
    in the face of a data center catastrophe

•   Needed a solution that could easily replicate data
    between two or more data centers

•   Needed the solution to store data in a safe and reliable
    way




                  http://www.couchbase.com/case-studies/bbc
The Solution
•   Using CouchDB to create a multi-master, multi-data
    center failover configuration

•   32 nodes in the cluster

    •   16 nodes in each of their two data centers

    •   8 primary nodes, 8 backup nodes

•   Terabyte of data

•   150 - 170 million requests per day

                   http://www.couchbase.com/case-studies/bbc
My Guess at BBC’s Replication Setup


                          App


                      Load
                     Balancer



P1 P2 P3 P4 P5 P6 P7 P8         P1 P2 P3 P4 P5 P6 P7 P8




B1 B2 B3 B4 B5 B6 B7 B8         B1 B2 B3 B4 B5 B6 B7 B8
Change Notifications
{"seq":12,"id":"foo","changes":
[{"rev":"1-23202479633c2b380f79507a776743d5"}]}
Polling

           GET /db/_changes
{"results":[
{"seq":1,"id":"test","changes":
[{"rev":"1-aaa8e2a031bca334f50b48b6682fb486"}]},
{"seq":2,"id":"test2","changes":
[{"rev":"1-e18422e6a82d0f2157d74b5dcf457997"}]}
],
"last_seq":2}
Polling

     GET /db/_changes?since=1

{"results":[
{"seq":2,"id":"test2","changes":
[{"rev":"1-e18422e6a82d0f2157d74b5dcf457997"}]}
],
"last_seq":2}
Polling
      GET /db/_changes?since=1
      &include_docs=true

{"results":[
{"seq":2,"id":"test2","changes":
[{"rev":"1-e18422e6a82d0f2157d74b5dcf457997"}],
,"doc":{"_id":"test2", "name":"John", "age":"33",
"_rev":"1-e18422e6a82d0f2157d74b5dcf457997"}}
],
"last_seq":2}
Long Polling

GET /db/_changes?feed=longpoll
&since=2
Continuous Changes


GET /db/_changes?feed=continuous
Filtered Changes
GET /db/_changes?filter=filters/
signal_employees

   function(doc, req) {
     if (doc.company == “Signal”) {
       return true;
     } else {
       return false;
     }
   }
Filtered Changes
GET /db/_changes?filter=filters/
employees&company=Signal

function(doc, req) {
  if (doc.company == req.query.company) {
    return true;
  } else {
    return false;
  }
}
Real World Example




    http://www.couchbase.com/case-studies/skechers
Sketchers
•   Already using CouchDB to help power
    www.sketchers.com

•   Utilized the _changes long poll feature to add a “What’s
    happening now” widget to the main page

•   Updates are processed in real time

•   The widget was written in just a few hours, with the
    majority of the code handling the display of the data



                http://www.couchbase.com/case-studies/skechers
Real World Example




http://www.dimagi.com/pulling-data-from-couchdb-to-a-relational-database-made-easy-with-_changes/
“Perhaps at the top of the list of ‘things that are annoying in CouchDB’ is
                            general reporting.”




                        http://browsertoolkit.com/fault-tolerance.png
dimagi
•   “Perhaps at the top of the list of ‘things that are annoying
    in CouchDB’ is general reporting.”

•   CouchDB views are not nearly as flexible as SQL

•   Using the _changes feed to mirror changes made in
    CouchDB over to a relational database

•   The relational database is used more extensive reporting

•   “Couch to SQL in 20 lines of code!”


http://www.dimagi.com/pulling-data-from-couchdb-to-a-relational-database-made-easy-with-_changes/
Real World Example


couchdb-lucene


    https://github.com/rnewson/couchdb-lucene
couchdb-lucene
•   Provides full text search functionality for data stored in
    CouchDB

•   Uses the continuous _changes feed to stay notified of the
    most recent changes in the database

•   Documents are included with change notifications

•   Index is updated shortly after document is saved in
    CouchDB



                  https://github.com/rnewson/couchdb-lucene
Mobile Device Support
Image credit: http://happyclouddesign.blogspot.com/
Image credit: http://gmflightlog.blogspot.com
Image credit: http://gmflightlog.blogspot.com
Image credit: http://happyclouddesign.blogspot.com/
Real World Example




   http://www.couchbase.com/case-studies/groupcomplete
The Problem
•   Looking to modernize mobile data collection (surveys, etc)

•   People collecting the data (mobile workers) have limited ability to
    review or modify data once it is submitted

•   Mobile workers work in a void, unable to collaborate with their
    team members, and increasing the likelihood of double-entry and
    duplicated effort

•   Mobile workers don’t have access to aggregated data, as this is
    usually done on the back end, where the data is sent

•   Access to a laptop or desktop is required to perform certain tasks

                   http://www.couchbase.com/case-studies/groupcomplete
The Solution
•   Cluster of CouchDB servers with shared forms, data, and profiles for
    mobile devices collecting data

•   A native application running on the device collects the data, and
    interacts with a local CouchDB server

•   Native application can access the data on the remote servers, or
    locally via replicated databases served by CouchDB running on the
    device

•   Since data can be stored locally, access is fast, and unaffected by spotty
    network availability


                     http://www.couchbase.com/case-studies/groupcomplete
The Solution
•   Mobile workers can easily share form templates and data

•   The application manages conflicts, allowing mobile workers to
    update, correct, and revise collected data at any time

•   Resolved conflicts are distributed to the team via standard
    replication, so everybody has the same data

•   Rich media (pictures, audio, video) stored as _attachments




                    http://www.couchbase.com/case-studies/groupcomplete
CouchApps
HTTP/1.1 200 OK
Server: CouchDB/1.0.2 (Erlang OTP/R14B)
Date: Tue, 07 Jun 2011 12:24:36 GMT
Content-Type: text/plain;charset=utf-8
Content-Length: 40
Cache-Control: must-revalidate

{"couchdb":"Welcome","version":"1.0.2"}
!=
Open Data
https://github.com/benoitc/afgwardiary
JSON != HTML
Show Functions


function(doc, req) {
  return '<h1>' + doc.title + '</h1>';
}




           http://guide.couchdb.org/draft/show.html
Show Functions
function(doc, req) {
  return {
    body : "<foo>" + doc.title + "</foo>",
    headers : {
      "Content-Type" : "application/xml",
      "X-My-Own-Header": "foo"
    }
  }
}


              http://guide.couchdb.org/draft/show.html
List Functions

function(head, req) {
  send('<ul>');
  while (row = getRow()) {
    send('<li>' + row.value + '</li>');
  }
  return('</ul>');
}
String concatenation to build HTML? Ewww!



      How do I get all of my Javascript into CouchDB?



Can I use my existing development tools?



    What about images, CSS files, and other resources?
The CouchApp Project
•   Scripts that allow you to easily deploy your CouchApp from your
    file system to CouchDB

•   Where the files live on your filesystem determine where they will
    be pushed to the database. myapp/views/foobar/map.js will be
    pushed to _design/myapp, into a view named foobar, as the map
    function.




                        https://github.com/couchapp/couchapp
The CouchApp Project
•   Evently - A declarative, CouchDB friendly jQuery library for writing
    event based Javascript applications

•   jquery.couch.js - Javascript library for communicating with CouchDB

•   jquery.pathbinder.js - Framework for triggering events based on
    paths in URL hash

•   mustache.js - A simple javascript template framework




                         https://github.com/couchapp/couchapp
Templates
<!DOCTYPE html>
<html>
  <head>
    <title>Example</title>
    <link rel=”stylesheet” href=”../../style/
screen.css” type=”text/css”>
  </head>

 <body>
   <h1 id=”post_title”>{{title}}</h1>
   <div id=”post_body”>{{body}}</div>
 </body>

  <script src=”../../script/awesome.js”></script>
</html>
Templates
// Show Function
function(doc, req) {
  var mustache = require("vendor/couchapp/lib/mustache");

  var data = {
    title : doc.title,
     body : doc.body
  };

  return mustache.to_html(this.templates.blog_post, data);
}
Real World Example




   http://www.couchbase.com/case-studies/incandescent
The Problem
•   Wanted to develop a web based solution for managing a
    veterinary clinic (managing patients, procedures, back
    office, etc)

•   Needed something that could operate in an environment
    without an internet connection

•   Wanted something flexible enough to scale up to a SaaS
    offering




               http://www.couchbase.com/case-studies/incandescent
The Solution
•   The application was built as an installable CouchApp

•   Written entirely in HTML and Javascript

•   Developed using Backbone.js

•   Platform independent, running on all platforms and
    browsers (iPad too!)

•   iPhone and Android versions in development




               http://www.couchbase.com/case-studies/incandescent
Resources
Resources
  CouchDB Project Website
  http://couchdb.apache.org


CouchDB: The Definitive Guide
  http://guide.couchdb.org


    CouchDB Project Wiki
http://wiki.apache.org/couchdb


         CouchApps
     http://couchapp.org
?
Thanks!
john@johnpwood.net
    @johnpwood

More Related Content

What's hot

Td gsm iit
Td gsm iitTd gsm iit
Td gsm iitTECOS
 
Lab1-DB-Cassandra
Lab1-DB-CassandraLab1-DB-Cassandra
Lab1-DB-CassandraLilia Sfaxi
 
Fiche de TP 3 sur les bases de données avec les SGBD(Système de Gestion des B...
Fiche de TP 3 sur les bases de données avec les SGBD(Système de Gestion des B...Fiche de TP 3 sur les bases de données avec les SGBD(Système de Gestion des B...
Fiche de TP 3 sur les bases de données avec les SGBD(Système de Gestion des B...ATPENSC-Group
 
C++ Template Metaprogramming
C++ Template MetaprogrammingC++ Template Metaprogramming
C++ Template MetaprogrammingAkira Takahashi
 
Alphorm.com Formation Laravel : Construire une Application de A à Z
Alphorm.com Formation Laravel : Construire une Application de A à ZAlphorm.com Formation Laravel : Construire une Application de A à Z
Alphorm.com Formation Laravel : Construire une Application de A à ZAlphorm
 
String function in my sql
String function in my sqlString function in my sql
String function in my sqlknowledgemart
 
Les memoires
Les memoiresLes memoires
Les memoiresdigidid
 
Correction TD Adressage IP.pdf
Correction  TD Adressage IP.pdfCorrection  TD Adressage IP.pdf
Correction TD Adressage IP.pdfssuser18776b
 
Cours data warehouse
Cours data warehouseCours data warehouse
Cours data warehousekhlifi z
 
Fiches Pratiques Excel 2007
Fiches Pratiques Excel 2007Fiches Pratiques Excel 2007
Fiches Pratiques Excel 2007Guillaume MAURIN
 
Stack & queue by stanly maarende
Stack & queue by stanly maarendeStack & queue by stanly maarende
Stack & queue by stanly maarendeSten Maarende
 
Bac blanc base de données
Bac blanc base de donnéesBac blanc base de données
Bac blanc base de donnéeslycee
 

What's hot (20)

Scala collection
Scala collectionScala collection
Scala collection
 
Oracle: Cursors
Oracle: CursorsOracle: Cursors
Oracle: Cursors
 
Td gsm iit
Td gsm iitTd gsm iit
Td gsm iit
 
Lab1-DB-Cassandra
Lab1-DB-CassandraLab1-DB-Cassandra
Lab1-DB-Cassandra
 
Fiche de TP 3 sur les bases de données avec les SGBD(Système de Gestion des B...
Fiche de TP 3 sur les bases de données avec les SGBD(Système de Gestion des B...Fiche de TP 3 sur les bases de données avec les SGBD(Système de Gestion des B...
Fiche de TP 3 sur les bases de données avec les SGBD(Système de Gestion des B...
 
C++ Template Metaprogramming
C++ Template MetaprogrammingC++ Template Metaprogramming
C++ Template Metaprogramming
 
Banking Database
Banking DatabaseBanking Database
Banking Database
 
Alphorm.com Formation Laravel : Construire une Application de A à Z
Alphorm.com Formation Laravel : Construire une Application de A à ZAlphorm.com Formation Laravel : Construire une Application de A à Z
Alphorm.com Formation Laravel : Construire une Application de A à Z
 
String function in my sql
String function in my sqlString function in my sql
String function in my sql
 
Les memoires
Les memoiresLes memoires
Les memoires
 
Correction TD Adressage IP.pdf
Correction  TD Adressage IP.pdfCorrection  TD Adressage IP.pdf
Correction TD Adressage IP.pdf
 
Cours data warehouse
Cours data warehouseCours data warehouse
Cours data warehouse
 
Chapitre 2 hadoop
Chapitre 2 hadoopChapitre 2 hadoop
Chapitre 2 hadoop
 
Fiches Pratiques Excel 2007
Fiches Pratiques Excel 2007Fiches Pratiques Excel 2007
Fiches Pratiques Excel 2007
 
TP 2 ACCESS
TP 2 ACCESSTP 2 ACCESS
TP 2 ACCESS
 
Stack & queue by stanly maarende
Stack & queue by stanly maarendeStack & queue by stanly maarende
Stack & queue by stanly maarende
 
Chapitre 3 spark
Chapitre 3 sparkChapitre 3 spark
Chapitre 3 spark
 
Sql
SqlSql
Sql
 
Bac blanc base de données
Bac blanc base de donnéesBac blanc base de données
Bac blanc base de données
 
Partie2BI-DW2019
Partie2BI-DW2019Partie2BI-DW2019
Partie2BI-DW2019
 

Viewers also liked

CouchDB – A Database for the Web
CouchDB – A Database for the WebCouchDB – A Database for the Web
CouchDB – A Database for the WebKarel Minarik
 
Migrating to CouchDB
Migrating to CouchDBMigrating to CouchDB
Migrating to CouchDBJohn Wood
 
OSCON 2011 Learning CouchDB
OSCON 2011 Learning CouchDBOSCON 2011 Learning CouchDB
OSCON 2011 Learning CouchDBBradley Holt
 
Learning To Relax
Learning To RelaxLearning To Relax
Learning To RelaxCloudant
 
MongoDB Case Study at NoSQL Now 2012
MongoDB Case Study at NoSQL Now 2012MongoDB Case Study at NoSQL Now 2012
MongoDB Case Study at NoSQL Now 2012Sean Laurent
 
ZendCon 2011 Learning CouchDB
ZendCon 2011 Learning CouchDBZendCon 2011 Learning CouchDB
ZendCon 2011 Learning CouchDBBradley Holt
 
CouchDB at its Core: Global Data Storage and Rich Incremental Indexing at Clo...
CouchDB at its Core: Global Data Storage and Rich Incremental Indexing at Clo...CouchDB at its Core: Global Data Storage and Rich Incremental Indexing at Clo...
CouchDB at its Core: Global Data Storage and Rich Incremental Indexing at Clo...StampedeCon
 
Couch Db In 60 Minutes
Couch Db In 60 MinutesCouch Db In 60 Minutes
Couch Db In 60 MinutesGeorge Ang
 
Couch db@nosql+taiwan
Couch db@nosql+taiwanCouch db@nosql+taiwan
Couch db@nosql+taiwanKenzou Yeh
 
CouchDB at New York PHP
CouchDB at New York PHPCouchDB at New York PHP
CouchDB at New York PHPBradley Holt
 
(GAM302) EA's Real-World Hurdles with Millions of Players in the Simpsons: Ta...
(GAM302) EA's Real-World Hurdles with Millions of Players in the Simpsons: Ta...(GAM302) EA's Real-World Hurdles with Millions of Players in the Simpsons: Ta...
(GAM302) EA's Real-World Hurdles with Millions of Players in the Simpsons: Ta...Amazon Web Services
 
Google - Bigtable
Google - BigtableGoogle - Bigtable
Google - Bigtable영원 서
 

Viewers also liked (20)

CouchDB-Lucene
CouchDB-LuceneCouchDB-Lucene
CouchDB-Lucene
 
CouchDB – A Database for the Web
CouchDB – A Database for the WebCouchDB – A Database for the Web
CouchDB – A Database for the Web
 
Tenacity
TenacityTenacity
Tenacity
 
Migrating to CouchDB
Migrating to CouchDBMigrating to CouchDB
Migrating to CouchDB
 
Couch db
Couch dbCouch db
Couch db
 
OSCON 2011 Learning CouchDB
OSCON 2011 Learning CouchDBOSCON 2011 Learning CouchDB
OSCON 2011 Learning CouchDB
 
Learning To Relax
Learning To RelaxLearning To Relax
Learning To Relax
 
MySQL Indexes
MySQL IndexesMySQL Indexes
MySQL Indexes
 
MongoDB Case Study at NoSQL Now 2012
MongoDB Case Study at NoSQL Now 2012MongoDB Case Study at NoSQL Now 2012
MongoDB Case Study at NoSQL Now 2012
 
ZendCon 2011 Learning CouchDB
ZendCon 2011 Learning CouchDBZendCon 2011 Learning CouchDB
ZendCon 2011 Learning CouchDB
 
CouchDB at its Core: Global Data Storage and Rich Incremental Indexing at Clo...
CouchDB at its Core: Global Data Storage and Rich Incremental Indexing at Clo...CouchDB at its Core: Global Data Storage and Rich Incremental Indexing at Clo...
CouchDB at its Core: Global Data Storage and Rich Incremental Indexing at Clo...
 
Apache CouchDB
Apache CouchDBApache CouchDB
Apache CouchDB
 
Couch Db In 60 Minutes
Couch Db In 60 MinutesCouch Db In 60 Minutes
Couch Db In 60 Minutes
 
Couch db@nosql+taiwan
Couch db@nosql+taiwanCouch db@nosql+taiwan
Couch db@nosql+taiwan
 
CouchDB at New York PHP
CouchDB at New York PHPCouchDB at New York PHP
CouchDB at New York PHP
 
(GAM302) EA's Real-World Hurdles with Millions of Players in the Simpsons: Ta...
(GAM302) EA's Real-World Hurdles with Millions of Players in the Simpsons: Ta...(GAM302) EA's Real-World Hurdles with Millions of Players in the Simpsons: Ta...
(GAM302) EA's Real-World Hurdles with Millions of Players in the Simpsons: Ta...
 
Couch db
Couch dbCouch db
Couch db
 
Couch db
Couch dbCouch db
Couch db
 
Intro To Couch Db
Intro To Couch DbIntro To Couch Db
Intro To Couch Db
 
Google - Bigtable
Google - BigtableGoogle - Bigtable
Google - Bigtable
 

Recently uploaded

IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 3652toLead Limited
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Servicegiselly40
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024Results
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...gurkirankumar98700
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Paola De la Torre
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 

Recently uploaded (20)

IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 

Real World CouchDB

  • 1. Real World John Wood Windy City DB 2011 @johnpwood
  • 3. • Software Developer at Signal • Coding for about 15 years • Working with CouchDB for 2.5 years (in production for about 2 years) • Enjoy tinkering with data storage solutions
  • 5. Document Database { “_id” : “2d7f015226a05b6940984bbe39004fde”, “_rev” : “2-477f6ab2dec6df185de1a078d270d8”, “first_name” : “John”, “last_name” : “Wood”, “interests” : [“hacking”, “fishing”, “reading”], “offspring” : [ { “name” : “Dylan”, “age” : 6 }, { “name” : “Chloe”, “age” : 3 } ] }
  • 6. Strong Focus on Replication
  • 7. RESTful API # Create POST http://localhost:5984/employees # Read GET http://localhost:5984/employees/1 # Update PUT http://localhost:5984/employees/1 # Delete DELETE http://localhost:5984/employees/1
  • 8. Queried and Indexed with MapReduce function(doc) { if (doc.first_name == “John”) emit(doc._id, 1); } function(keys, values, rereduce) { return sum(values); }
  • 11. Views
  • 12. MapReduce // Map function(doc) { emit(doc._id, 1); } // Reduce function(keys, values, rereduce) { return sum(values); }
  • 13. MapReduce // Map function(doc) { if (doc.dependents) { for (i in doc.dependents) { emit(doc._id, doc.dependents[i]); } } } // Reduce _count
  • 14. MapReduce function(keys, values, rereduce) { function sum(type_counts, totals, status) { if (type_counts[status]) { // OK or ERR if (!totals[status]) { totals[status] = new Object(); } var status_totals = totals[status]; var status_type_counts = type_counts[status]; for (key in status_type_counts) { // MO, MT, CM, etc. var count = status_type_counts[key]; if (!status_totals[key]) { status_totals[key] = count; } else { status_totals[key] += count; } } } } var totals = new Object(); // values should be something like // {"OK":{"MO":1234,"MT":1000,"CM":20},"ERR":{"MO":1,"MT": 1}} for (i = 0; i < values.length; i++) { var message_count = values[i]; sum(message_count, totals, 'OK'); } return totals; }
  • 15. Design Documents { "_id": "_design/stats", "views": { "total_employees": { "map": "function(doc) { emit(doc._id, 1); }", "reduce": "function(keys, values, rereduce) { return sum(values); }" }, "by_lastname": { "map": "function(doc) { emit(doc.last_name, null); }" }, "dependents": { "map": "function(doc) { if (doc.dependents) { for (i in doc.dependents) { emit(doc._id, doc.dependents[i]); } } }", "reduce": "_count" } } }
  • 16. { "_id": "1", "first_name": "Robert", { "last_name": "Johnson", "_id": "4", "date_hired": "2010/01/10", "first_name": "Bob", "dependents": [ { { "last_name": "Smith", { "first_name": "Margie", "last_name": "Johnson" }, "_id": "2", "_id": "3", "salary": 80000, { "first_name": "Charlie", "last_name": "Johnson" }, "first_name": "Jim", "first_name": "Sally", "date_hired": "2010/03/11", { "first_name": "Sophie", "last_name": "Johnson" } "last_name": "Jones", "last_name": "Stevenson", "dependents": [ ], "date_hired": "2010/02/11", "date_hired": "2010/04/23", { "first_name": "Susan", "last_name": "Smith" } "salary": 250000 "salary": 150000 "salary": 100000 ] } } } } MapReduce {"total_rows":4,"offset":0,"rows":[ {"id":"1","key":"1","value":{"first_name":"Margie","last_name":"Johnson"}}, {"id":"1","key":"1","value":{"first_name":"Charlie","last_name":"Johnson"}}, {"id":"1","key":"1","value":{"first_name":"Sophie","last_name":"Johnson"}}, {"id":"4","key":"4","value":{"first_name":"Susan","last_name":"Smith"}} ]}
  • 17. { "_id": "1", "first_name": "Robert", { "last_name": "Johnson", "_id": "4", "date_hired": "2010/01/10", "first_name": "Bob", "dependents": [ { { "last_name": "Smith", { "first_name": "Margie", "last_name": "Johnson" }, "_id": "2", "_id": "3", "salary": 80000, { "first_name": "Charlie", "last_name": "Johnson" }, "first_name": "Jim", "first_name": "Sally", "date_hired": "2010/03/11", { "first_name": "Sophie", "last_name": "Johnson" } "last_name": "Jones", "last_name": "Stevenson", "dependents": [ ], "date_hired": "2010/02/11", "date_hired": "2010/04/23", { "first_name": "Susan", "last_name": "Smith" } "salary": 250000 "salary": 150000 "salary": 100000 ] } } } } MapReduce {"rows":[ {"key":null,"value":4} ]}
  • 18. { "_id": "1", "first_name": "Robert", { "last_name": "Johnson", "_id": "4", "date_hired": "2010/01/10", "first_name": "Bob", "dependents": [ { { "last_name": "Smith", { "first_name": "Margie", "last_name": "Johnson" }, "_id": "2", "_id": "3", "salary": 80000, { "first_name": "Charlie", "last_name": "Johnson" }, "first_name": "Jim", "first_name": "Sally", "date_hired": "2010/03/11", { "first_name": "Sophie", "last_name": "Johnson" } "last_name": "Jones", "last_name": "Stevenson", "dependents": [ ], "date_hired": "2010/02/11", "date_hired": "2010/04/23", { "first_name": "Susan", "last_name": "Smith" } "salary": 250000 "salary": 150000 "salary": 100000 ] } } } } MapReduce {"rows":[ {"key":"1","value":3}, {"key":"4","value":1} ]}
  • 19. View Structure http://guide.couchdb.org/editions/1/en/views.html
  • 20. View Structure ?key="ch" http://guide.couchdb.org/editions/1/en/views.html
  • 22. The Problem • Reports that utilized data in some large tables (30M+ rows) were taking a very long to create • Increasing query execution times • Occasional page timeouts • Limited resources for super powered hardware or the leading relational database product • Database migrations on these large tables were taking an increasingly long time to run
  • 23. The Solution • Using CouchDB as an archive database • Migrated old data in tables to CouchDB, dramatically reducing the tables sizes, speeding up queries that were still hitting those tables • Re-wrote SQL queries as views to fetch data from the archive database, dramatically reducing the amount of time needed to fetch the old data • Views updated nightly with the new set of archived data
  • 29. Filtered function(doc, req) { if (doc.type && doc.type == "foo") { return true; } else { return false; } }
  • 30. Filtered function(doc, req) { if (doc.type && doc.type == req.query.doc_type) { return true; } else { return false; } }
  • 31. Named
  • 34. Finding Conflicts function(doc) { if (doc._conflicts) { emit(doc._conflicts, null); } } {"total_rows":1,"offset":0,"rows":[ {"id":"foo","key": ["2-7c971bb974251ae8541b8fe045964219"],"value":null} ]} http://guide.couchdb.org/draft/conflicts.html
  • 35. Resolving Conflicts # Step 1 PUT /db/document {... merged data ...} # Step 2 DELETE /db/document? rev=2-7c971bb974251ae8541b8fe045964219
  • 36. Real World Example http://www.couchbase.com/case-studies/bbc
  • 37. The Problem • Need to make sure site was always up and available, even in the face of a data center catastrophe • Needed a solution that could easily replicate data between two or more data centers • Needed the solution to store data in a safe and reliable way http://www.couchbase.com/case-studies/bbc
  • 38. The Solution • Using CouchDB to create a multi-master, multi-data center failover configuration • 32 nodes in the cluster • 16 nodes in each of their two data centers • 8 primary nodes, 8 backup nodes • Terabyte of data • 150 - 170 million requests per day http://www.couchbase.com/case-studies/bbc
  • 39. My Guess at BBC’s Replication Setup App Load Balancer P1 P2 P3 P4 P5 P6 P7 P8 P1 P2 P3 P4 P5 P6 P7 P8 B1 B2 B3 B4 B5 B6 B7 B8 B1 B2 B3 B4 B5 B6 B7 B8
  • 42. Polling GET /db/_changes {"results":[ {"seq":1,"id":"test","changes": [{"rev":"1-aaa8e2a031bca334f50b48b6682fb486"}]}, {"seq":2,"id":"test2","changes": [{"rev":"1-e18422e6a82d0f2157d74b5dcf457997"}]} ], "last_seq":2}
  • 43. Polling GET /db/_changes?since=1 {"results":[ {"seq":2,"id":"test2","changes": [{"rev":"1-e18422e6a82d0f2157d74b5dcf457997"}]} ], "last_seq":2}
  • 44. Polling GET /db/_changes?since=1 &include_docs=true {"results":[ {"seq":2,"id":"test2","changes": [{"rev":"1-e18422e6a82d0f2157d74b5dcf457997"}], ,"doc":{"_id":"test2", "name":"John", "age":"33", "_rev":"1-e18422e6a82d0f2157d74b5dcf457997"}} ], "last_seq":2}
  • 47. Filtered Changes GET /db/_changes?filter=filters/ signal_employees function(doc, req) { if (doc.company == “Signal”) { return true; } else { return false; } }
  • 48. Filtered Changes GET /db/_changes?filter=filters/ employees&company=Signal function(doc, req) { if (doc.company == req.query.company) { return true; } else { return false; } }
  • 49. Real World Example http://www.couchbase.com/case-studies/skechers
  • 50. Sketchers • Already using CouchDB to help power www.sketchers.com • Utilized the _changes long poll feature to add a “What’s happening now” widget to the main page • Updates are processed in real time • The widget was written in just a few hours, with the majority of the code handling the display of the data http://www.couchbase.com/case-studies/skechers
  • 52. “Perhaps at the top of the list of ‘things that are annoying in CouchDB’ is general reporting.” http://browsertoolkit.com/fault-tolerance.png
  • 53. dimagi • “Perhaps at the top of the list of ‘things that are annoying in CouchDB’ is general reporting.” • CouchDB views are not nearly as flexible as SQL • Using the _changes feed to mirror changes made in CouchDB over to a relational database • The relational database is used more extensive reporting • “Couch to SQL in 20 lines of code!” http://www.dimagi.com/pulling-data-from-couchdb-to-a-relational-database-made-easy-with-_changes/
  • 54. Real World Example couchdb-lucene https://github.com/rnewson/couchdb-lucene
  • 55. couchdb-lucene • Provides full text search functionality for data stored in CouchDB • Uses the continuous _changes feed to stay notified of the most recent changes in the database • Documents are included with change notifications • Index is updated shortly after document is saved in CouchDB https://github.com/rnewson/couchdb-lucene
  • 57.
  • 62.
  • 63. Real World Example http://www.couchbase.com/case-studies/groupcomplete
  • 64. The Problem • Looking to modernize mobile data collection (surveys, etc) • People collecting the data (mobile workers) have limited ability to review or modify data once it is submitted • Mobile workers work in a void, unable to collaborate with their team members, and increasing the likelihood of double-entry and duplicated effort • Mobile workers don’t have access to aggregated data, as this is usually done on the back end, where the data is sent • Access to a laptop or desktop is required to perform certain tasks http://www.couchbase.com/case-studies/groupcomplete
  • 65. The Solution • Cluster of CouchDB servers with shared forms, data, and profiles for mobile devices collecting data • A native application running on the device collects the data, and interacts with a local CouchDB server • Native application can access the data on the remote servers, or locally via replicated databases served by CouchDB running on the device • Since data can be stored locally, access is fast, and unaffected by spotty network availability http://www.couchbase.com/case-studies/groupcomplete
  • 66. The Solution • Mobile workers can easily share form templates and data • The application manages conflicts, allowing mobile workers to update, correct, and revise collected data at any time • Resolved conflicts are distributed to the team via standard replication, so everybody has the same data • Rich media (pictures, audio, video) stored as _attachments http://www.couchbase.com/case-studies/groupcomplete
  • 68. HTTP/1.1 200 OK Server: CouchDB/1.0.2 (Erlang OTP/R14B) Date: Tue, 07 Jun 2011 12:24:36 GMT Content-Type: text/plain;charset=utf-8 Content-Length: 40 Cache-Control: must-revalidate {"couchdb":"Welcome","version":"1.0.2"}
  • 69. !=
  • 70.
  • 71.
  • 72.
  • 73.
  • 77. Show Functions function(doc, req) { return '<h1>' + doc.title + '</h1>'; } http://guide.couchdb.org/draft/show.html
  • 78. Show Functions function(doc, req) { return { body : "<foo>" + doc.title + "</foo>", headers : { "Content-Type" : "application/xml", "X-My-Own-Header": "foo" } } } http://guide.couchdb.org/draft/show.html
  • 79. List Functions function(head, req) { send('<ul>'); while (row = getRow()) { send('<li>' + row.value + '</li>'); } return('</ul>'); }
  • 80. String concatenation to build HTML? Ewww! How do I get all of my Javascript into CouchDB? Can I use my existing development tools? What about images, CSS files, and other resources?
  • 81. The CouchApp Project • Scripts that allow you to easily deploy your CouchApp from your file system to CouchDB • Where the files live on your filesystem determine where they will be pushed to the database. myapp/views/foobar/map.js will be pushed to _design/myapp, into a view named foobar, as the map function. https://github.com/couchapp/couchapp
  • 82. The CouchApp Project • Evently - A declarative, CouchDB friendly jQuery library for writing event based Javascript applications • jquery.couch.js - Javascript library for communicating with CouchDB • jquery.pathbinder.js - Framework for triggering events based on paths in URL hash • mustache.js - A simple javascript template framework https://github.com/couchapp/couchapp
  • 83. Templates <!DOCTYPE html> <html> <head> <title>Example</title> <link rel=”stylesheet” href=”../../style/ screen.css” type=”text/css”> </head> <body> <h1 id=”post_title”>{{title}}</h1> <div id=”post_body”>{{body}}</div> </body> <script src=”../../script/awesome.js”></script> </html>
  • 84. Templates // Show Function function(doc, req) {   var mustache = require("vendor/couchapp/lib/mustache");   var data = {     title : doc.title, body : doc.body   };   return mustache.to_html(this.templates.blog_post, data); }
  • 85. Real World Example http://www.couchbase.com/case-studies/incandescent
  • 86. The Problem • Wanted to develop a web based solution for managing a veterinary clinic (managing patients, procedures, back office, etc) • Needed something that could operate in an environment without an internet connection • Wanted something flexible enough to scale up to a SaaS offering http://www.couchbase.com/case-studies/incandescent
  • 87. The Solution • The application was built as an installable CouchApp • Written entirely in HTML and Javascript • Developed using Backbone.js • Platform independent, running on all platforms and browsers (iPad too!) • iPhone and Android versions in development http://www.couchbase.com/case-studies/incandescent
  • 89. Resources CouchDB Project Website http://couchdb.apache.org CouchDB: The Definitive Guide http://guide.couchdb.org CouchDB Project Wiki http://wiki.apache.org/couchdb CouchApps http://couchapp.org
  • 90. ?

Editor's Notes

  1. * In this talk I&amp;#x2019;ll be discussing some of CouchDB&amp;#x2019;s key features, and how they&amp;#x2019;re being used in the real world\n
  2. \n
  3. * Signal provides a web based service for conducting and managing digital marketing campaigns over SMS, email, web, facebook, twitter, and other channels\n\n* We have been working with NoSQL databases lately because we collect a lot of data while these campaigns are in progress\n\n* In addition, our customers collect a lot of data about their customers\n\n* Managing all of this data has proven challenging, and we&amp;#x2019;re always looking for better ways to do it\n
  4. \n
  5. * Documents must contain valid JSON\n\n* _id must be unique in the database\n\n* Other than that, no requirements. Documents in the same database can be wildly different from one another.\n\n* Documents are self contained. Relationships are not supported.\n\n* Binary attachments can be stored in the _attachments property\n
  6. * Designed with replication and off line operation in mind\n\n* Incredibly easy to replicate from one database to another\n
  7. * All interaction is done via HTTP\n\n* Administration too (creating databases, triggering replication, triggering a compaction, etc) is done via HTTP\n\n* Documents are treated as resources\n
  8. * This simple map function will emit the doc id and a &amp;#x201C;1&amp;#x201D; for every document with a first_name of &amp;#x201C;John&amp;#x201D;. The reduce function then sums those values, effectively giving me a count of all documents in the database with first_name of &amp;#x201C;John&amp;#x201D;.\n\n* CouchDB does not support adhoc queries\n\n* In order to query data, CouchDB must first build an index by passing all of the documents in the database through a map function, and then optionally reducing their results\n\n* MapReduce can be slow on large datasets. But once the index is built, queries are fast.\n\n\n
  9. * CouchDB has a crash only design where the server does not go through a shutdown process.\n\n* You can kill the process at any time, and your data will be safe. In fact, killing the process is the way you shut down CouchDB.\n\n* Uses multi version concurrency control, meaning it never overwrites committed data. Instead, it always appends new data. This dramatically reduces the risk of data corruption.\n\n
  10. * Erlang OTP has a strong emphasis on concurrent operations and fault tolerance, something that CouchDB takes advantage of\n
  11. * Views are how data is queried using CouchDB\n\n* Views add structure back to unstructured data, so it can be queried\n\n* Views are made up of a map function, and optional reduce function, which aggregates the results of the map function\n
  12. * Views build indexes of key/value pairs\n\n* Keys can be single values, or arrays of values\n\n* Values can be just about anything, including single values, hashes, or arrays\n\n* View results are sorted by key (can be in ascending or descending order)\n\n* View Indexes are stored on disk separately from the database\n\n* Once built, indexes are updated incrementally as documents are added/updated/deleted - the biggest difference between Google/Hadoop style MapReduce, which map through the entire dataset for each execution\n\n
  13. * This map function checks to see if the document has a property called &amp;#x201C;dependents&amp;#x201D;. If it does, it loops through all of the elements in the dependents array, emitting the element in the array. The reduce function then counts the number of dependents emitted.\n\n* Map functions have access to the document, and can interrogate its data\n\n* A single document may emit 0 or many key/value pairs\n\n* CouchDB has a few built in reduce functions, like _count, _sum, and _stats\n\n
  14. * Views can do more than simply count and sum single values\n\n* Views can get complicated, depending on the values they are working with\n\n* This example basically sums the values in a hash\n\n
  15. * Views are stored in special documents called design documents.\n\n* Views stored in the same design document share a data structure on disk.\n\n* This is important to note, because changes that require one view to be rebuilt will impact all views in the same design document.\n\n* Also, view indexes can take up a lot of space on disk. Grouping related views in the same design document is a way to save on disk space.\n\n* This is something to keep in mind when you are designing views.\n\n
  16. * Here is some sample output from the map function we saw previously that emitted information about a document&amp;#x2019;s dependents\n\n* You can instruct CouchDB not to reduce the results via a query parameter\n\n
  17. * Here is the reduced result, which is a count of all of the dependents in the database\n\n
  18. * The view API also lets you group your results by key\n\n* Here we see the number of dependents in each document, broken out by the document&amp;#x2019;s id\n\n\n
  19. * View indexes are stored as a b+ tree on disk\n\n* B+ trees are nice because they are very flat data structures, and use a minimal number of disk seeks to fetch data.\n\n* Leaf nodes store results, parent nodes store reduction of child results\n
  20. * When CouchDB determines that a query would include all of the sub nodes of a parent node, it&amp;#x2019;ll simply pull the value from the parent node, preventing it from having to rereduce all of the children\n\n* It then pulls the values from the other nodes, and runs the reduce function with all of the values it pulled.\n\n* Here, it pulls the &amp;#x201C;3&amp;#x201D; from the parent, and then the &amp;#x201C;1&amp;#x201D; from the element to the left, and reduces those values to come up with the result.\n\n
  21. \n
  22. \n
  23. \n
  24. * CouchDB&amp;#x2019;s bread and butter. This is what it was built for.\n\n* Synchronizes two copies of the same database, either on the same database server or different database servers\n\n
  25. * Simply tells CouchDB what database to replicate, and where to replicate it\n\n* Replication is designed to handle failure gracefully. Will simply pick up where it left off.\n
  26. * Replicates changes from one database to the other\n\n* CouchDB will compare databases, finding documents that differ, and then submit a batch of changed documents to the target (until all changes are transferred)\n\n* CouchDB increments a sequence number every time the DB is changed. CouchDB uses that sequence number to help find differences between two databases.\n\n
  27. * Bidirectional replication simply consists of two unidirectional replication requests, with the source and target switched\n\n* When complete, both databases will be in sync\n
  28. * Keeps a HTTP connection open, and streams changes to the target\n\n* Replicates changes as they are committed\n\n
  29. * All documents eligible for replication are fed through a filter function. The document will only be replicated if the function returns true.\n\n* Provide filter function and any query params in the request : &quot;filter&quot;:&quot;myddoc/myfilter&quot;, &quot;query_params&quot;: {&quot;key&quot;:&quot;value&quot;}\n\n
  30. * Filter functions also have access to the replication request, which can be used to support more dynamic behavior\n
  31. * Provide doc_ids in the request : &quot;doc_ids&quot;:[&quot;foo&quot;,&quot;bar&quot;,&quot;baz]\n\n
  32. * CouchDB was designed to operate offline. If both databases continue to process updates while &amp;#x201C;disconnected&amp;#x201D; from each other, conflicts are bound to happen. A conflict happens when the same document is updated in both databases.\n\n* During replication, CouchDB will detect when there are multiple versions of the same document, and CouchDB records the conflict\n\n* A winner is chosen by CouchDB, because it needs a &amp;#x201C;latest&amp;#x201D; document\n\n* The losing revision is stored as the previous version of the document, and is made available for merging\n
  33. * Losing revisions are identified by the _conflicts property\n\n* CouchDB does not attempt to merge conflicting documents\n\n
  34. * Best way of finding conflicting documents is via a view, like this one\n\n* Could have a job that runs this view periodically, and merges conflicting documents\n\n* You can also resolve conflicts on read. By default, CouchDB will not return the _conflicts property when a document is fetched. However, it will if you include a parameter telling it to do so in your HTTP request to fetch the document. With that information, you can take care of conflicts as you encounter them.\n\n
  35. * To resolve conflicts, save the merged content as a new version of the document, and delete the conflicting revisions.\n\n* Compacting the database will also remove losing revisions\n
  36. \n
  37. \n
  38. \n
  39. * Enough replication going on here that these data centers could easily be confused for a rabbit farm\n\n* Red line = CouchDB Continuous Replication\n\n* Each primary server capable of handling reads and writes, for scalability\n\n* Matching primary servers in each datacenter are continuously replicating changes to each other, to keep them in sync\n\n* In addition, each primary continuously replicates changes to its backup, so the backup is ready to take over at any point in time\n\n
  40. * API for being notified of changes in the database\n
  41. * The contents of an item in the change notification feed:\nseq - The update_seq number in the database that was created for this change\nid - The id of the document that was changed\nchanges - What was changed in the document\n
  42. * Polling will pull changes by request\n\n* When no arguments are specified, all changes will be displayed\n\n
  43. * You can easily get all changes since a given sequence number\n
  44. * You can include the document content in the change notification with the include_docs query parameter\n\n* Avoids another call to CouchDB for document information\n
  45. * For less frequent updates\n\n* Will hold the connection open until we get an update. Connection is closed after update is received.\n\n* Using this avoids the need to continuously poll for changes\n
  46. * Will hold the connection open indefinitely.\n\n* Results are streamed in as individual chunks of JSON, making them easy to parse.\n
  47. * Like replication, you have the ability to filter change notifications\n\n* Only changed documents that pass the specified filter function by returning true will be sent to the client\n
  48. * Filter functions have access to a request object, which includes any query parameters that were specified\n\n* Provides the ability for more dynamic functionality\n
  49. \n
  50. \n
  51. \n
  52. \n
  53. \n
  54. \n
  55. \n
  56. * One area where CouchDB really stands out is mobile device support\n
  57. * CouchDB runs natively on iOS (iPhone and iPad) and Android\n\n* WebOS has a local storage solution capable of syncing with CouchDB\n\n
  58. * Many native applications pull data over the network from a remote service\n\n* This works fine when the network is nice\n
  59. * But sometimes the network is mean. No bars. Spotty coverage. Too much traffic.\n\n* These apps either don&amp;#x2019;t work, will only give you access to features that don&amp;#x2019;t require data from the network, or are incredibly slow when there are network issues\n
  60. * If your app uses CouchDB, you&amp;#x2019;d be able to continue interacting with your data locally when the network is unavailable\n\n* Data access will be quick and snappy, regardless\n\n
  61. * When the network becomes available, you can easily sync your changes to a remote CouchDB instance\n\n* Your app doesn&amp;#x2019;t need to worry about replicating changes. CouchDB will do it for you.\n\n* Once synced, your changes will be available elsewhere\n\n
  62. * CouchDB has minimal impact on battery life when idling\n\n* It&amp;#x2019;s also well know that radio transmissions are very expensive with regards to power consumption. Apps that use local data will be much easier on the battery than apps that continuously pull data over the network.\n\n
  63. \n
  64. \n
  65. \n
  66. \n
  67. * CouchApps are HTML/Javascript applications that are served right out of CouchDB\n\n* I&amp;#x2019;ve read that one of CouchDB&amp;#x2019;s original design goals was to one day be able to serve web applications, which highlights how different it really is from traditional databases\n
  68. * CouchDB speaks HTTP\n\n* Can easily serve static files that are stored as attachments inside a document\n\n* Also supports URL rewriting and Virtual Hosts\n\n
  69. * Just because CouchDB can serve your web application does not mean it&amp;#x2019;s a full blown web framework\n\n* But, some applications don&amp;#x2019;t need a fully featured web framework\n\n* In fact, more and more applications are falling into this category. Many believe that this is the future of web applications.\n\n* Javascript frameworks like Backbone.js and Spine, along with template frameworks like mustache.js, are making it much easier to write web applications entirely in Javascript and HTML that run on the client, only using the server to fetch and store data. This is the sort of application that would be great as a CouchApp.\n
  70. * Traditional 3-tier architecture\n\n* Client machines, web servers, and a database\n
  71. * CouchApps eliminate the need for separate web and database servers, since CouchDB can both serve the application, and act as the database\n\n* Can easily deploy multiple CouchDB instances, replicating changes between them, for scalability\n\n* CouchDB provides an Etags header, which if used properly can further reduce the load on the servers\n\n* If this architecture works, then....\n
  72. * If your application is capable of talking to CouchDB remotely, then it can just as easily talk to a local instance of CouchDB\n\n* Only difference in the application is the URL used to connect to CouchDB\n\n* This scale down architecture allows you to replicate your application and data to a local instance of CouchDB, and run your application in &amp;#x201C;offline&amp;#x201D; mode\n\n
  73. * No need for a powerful client machine\n\n* If your CouchApp is optimized for viewing on a mobile device, the same scale down architecture applies to mobile devices as well\n
  74. * Not only are CouchApps open source by nature, but they are also open data\n\n
  75. * Kabul War Diary CouchApp is a perfect example of this\n\n* This is a CouchApp created by one of the CouchDB committers\n\n* Wraps wiki leak data in application that allows you to easily browse it\n\n* Because it&amp;#x2019;s a CouchApp, the data and application can easily, via a single command, be replicated to any CouchDB instance\n\n
  76. * How can CouchDB serve web applications when the documents are stored in JSON?\n\n* My web browser can&amp;#x2019;t make a pretty web page out of JSON. It needs HTML.\n\n
  77. * Show functions let you transform documents into some other format (HTML, XML, etc)\n\n* This example simply throws the document&amp;#x2019;s title inside an HTML heading tag\n\n* Stored in design documents like views\n\n* Show functions cannot update the database, and are side effect free. Hence, the output can easily be cached.\n
  78. * CouchDB lets you set response headers as well\n
  79. * List functions let you transform view results into something else (HTML, CSV files, etc)\n\n* The send function sends a chunk of HTML to the client\n\n* The return function sends the final chunk\n\n* This function simply sticks the &amp;#x201C;values&amp;#x201D; of the view results inside an unordered list\n\n* Since we&amp;#x2019;re sending data to the client programmatically, we can filter and aggregate view result data on the fly, letting you tweak the data before sending it to the client\n\n* Like show functions, list functions cannot update the database and are side effect free.\n
  80. * Right now there are probably a few questions running through your head\n
  81. * Enables you to continue using the tools your familiar with\n\n
  82. * The CouchApp project also ships with serval javascript libraries that can help with development\n
  83. * This is an example mustache.js HTML template\n\n* The post&amp;#x2019;s title and body are included via template variables, seen here in green\n\n* CSS files, javascript files, images, and other resources can be referenced using relative paths. Simply place them in the appropriate spot in the CouchApp directory structure, and it will just work.\n\n* Now, this looks a lot more like what web developers are used to working with\n\n
  84. * Templates can be rendered from show functions, list functions, or functions triggered by event callbacks\n\n* This show function renders a blog post using the template in blog_post.html with the data in the data hash\n\n
  85. \n
  86. \n
  87. * Backbone.js provides an MVC like structure to Javascript applications\n
  88. \n
  89. * Some resources for finding out more about CouchDB\n
  90. \n
  91. \n