SlideShare una empresa de Scribd logo
1 de 85
Descargar para leer sin conexión
VS
Database
No SQL
Key-Value Database
Document Database
Document
         {
             "day": [ 2010, 01, 23 ],
             "products": {
                 "apple": {
                     "price": 10



Key ->
                     "quantity": 6
                 },
                 "kiwi": {
                     "price": 20
                     "quantity": 2
                 }
             },
             "checkout": 100
         }
Couchdb                           Mongodb

Data Model      Document-Oriented (JSON)           Document-Oriented (BSON)


 Interface              HTTP/REST                 Custom protocol over TCP/IP


  Object                                          Database contains Collections
                Database contains Documents
  Storage                                        Collections contains Documents

                                                 Map/Reduce (javascript) creating
  Query       Map/Reduce (javascript + others)
                                                 Collections + Object-Based query
  Method       creating Views + Range queries
                                                              language
                 Master-Master with custom
Replication                                                Master-Slave
                 conflict resolution functions

              MVCC (Multi Version Concurrency
Concurrency                                              Update in-place
                        Control)


 Written In                Erlang                             C++
Map/Reduce???
Example: Tickets




{                      {                      {                      {
    "id": 1,               "id": 2,               "id": 3,               "id": 4,
    "day": 20100123,       "day": 20100123,       "day": 20100123,       "day": 20100123,
    "checkout": 100        "checkout": 42         "checkout": 215        "checkout": 73
}                      }                      }                      }
Sum(checkout)?




{                      {                      {                      {
    "id": 1,               "id": 2,               "id": 3,               "id": 4,
    "day": 20100123,       "day": 20100123,       "day": 20100123,       "day": 20100123,
    "checkout": 100        "checkout": 42         "checkout": 215        "checkout": 73
}                      }                      }                      }
Map: emit(checkout)




       100                     42                    215                     73


{                      {                      {                      {
    "id": 1,               "id": 2,               "id": 3,               "id": 4,
    "day": 20100123,       "day": 20100123,       "day": 20100123,       "day": 20100123,
    "checkout": 100        "checkout": 42         "checkout": 215        "checkout": 73
}                      }                      }                      }
Reduce: sum(checkouts)



                   142                                          288



        100                     42                    215                     73


 {                      {                      {                      {
     "id": 1,               "id": 2,               "id": 3,               "id": 4,
     "day": 20100123,       "day": 20100123,       "day": 20100123,       "day": 20100123,
     "checkout": 100        "checkout": 42         "checkout": 215        "checkout": 73
 }                      }                      }                      }
Reduce: sum(checkouts)

                                         430



                   142                                          288



        100                     42                    215                     73


 {                      {                      {                      {
     "id": 1,               "id": 2,               "id": 3,               "id": 4,
     "day": 20100123,       "day": 20100123,       "day": 20100123,       "day": 20100123,
     "checkout": 100        "checkout": 42         "checkout": 215        "checkout": 73
 }                      }                      }                      }
Reduce must be associative

reduce(         100         42        215          73    ) ==   430




                      Must be equal to
reduce(

       reduce(        100        42         ) ==        142



       reduce(        215        73         ) ==        288




) ==      430
SELECT
SUM(checkout)
 FROM ticket
    ?!?!?!?
Inherently distributed

                                        430



                  142                                          288



       100                     42                     215                    73


{                      {                      {                      {
    "id": 1,               "id": 2,               "id": 3,               "id": 4,
    "day": 20100123,       "day": 20100123,       "day": 20100123,       "day": 20100123,
    "checkout": 100        "checkout": 42         "checkout": 215        "checkout": 73
}                      }                      }                      }
Logaritmic Update

                                        430



                  142                                          288



       100                     42                     215                    73


{                      {                      {                      {
    "id": 1,               "id": 2,               "id": 3,               "id": 4,
    "day": 20100123,       "day": 20100123,       "day": 20100123,       "day": 20100123,
    "checkout": 100        "checkout": 42         "checkout": 210        "checkout": 73
}                      }                      }                      }
Logaritmic Update

                                        430



                  142                                          288



       100                     42                     210                    73


{                      {                      {                      {
    "id": 1,               "id": 2,               "id": 3,               "id": 4,
    "day": 20100123,       "day": 20100123,       "day": 20100123,       "day": 20100123,
    "checkout": 100        "checkout": 42         "checkout": 210        "checkout": 73
}                      }                      }                      }
Logaritmic Update

                                        430



                  142                                          283



       100                     42                     210                    73


{                      {                      {                      {
    "id": 1,               "id": 2,               "id": 3,               "id": 4,
    "day": 20100123,       "day": 20100123,       "day": 20100123,       "day": 20100123,
    "checkout": 100        "checkout": 42         "checkout": 210        "checkout": 73
}                      }                      }                      }
Logaritmic Update

                                        425



                  142                                          283



       100                     42                     210                    73


{                      {                      {                      {
    "id": 1,               "id": 2,               "id": 3,               "id": 4,
    "day": 20100123,       "day": 20100123,       "day": 20100123,       "day": 20100123,
    "checkout": 100        "checkout": 42         "checkout": 210        "checkout": 73
}                      }                      }                      }
Logaritmic Update
Sum(checkout)
Sum(checkout)
Sum(checkout)
Sum(checkout)
Sum(checkout)
# START SERVER
$ ~/opt/mongodb-1.3.0/bin/mongod 
  --dbpath=./db/mongodb.01/ 
  --logpath=./log/mongodb.01 
  --port 30001



# START SHELL
$ ~/opt/mongodb-1.3.0/bin/mongo localhost:30001
connecting to: localhost:30001/test
type "help" for help
> show dbs
admin
local
Sum(checkout)
> use checkout
switched to db checkout

>   db.tickets.save({   "_id":   1,   "day":   20100123,   "checkout":   100 })
>   db.tickets.save({   "_id":   2,   "day":   20100123,   "checkout":   42 })
>   db.tickets.save({   "_id":   3,   "day":   20100123,   "checkout":   215 })
>   db.tickets.save({   "_id":   4,   "day":   20100123,   "checkout":   73 })

> db.tickets.count()
4

> db.tickets.find()
{ "_id" : 1, "day" : 20100123, "checkout" : 100 }
...

> db.tickets.find({ "_id": 1 })
{ "_id" : 1, "day" : 20100123, "checkout" : 100 }
Sum(checkout)
> var map = function() {
... emit(null, this.checkout)
... }

> var reduce = function(key, values) {
... var sum = 0
... for (var index in values) sum += values[index]
... return sum
... }
Sum(checkout)
                               Temporary Collection
> sumOfCheckouts = db.tickets.mapReduce(map, reduce)
{
  "result" : "tmp.mr.mapreduce_1263717818_4",
  "timeMillis" : 8,
  "counts" : { "input" : 4, "emit" : 4, "output" : 1 },
  "ok" : 1
}

> db.getCollectionNames()
[
  "tickets",
  "tmp.mr.mapreduce_1263717818_4",
]

> db[sumOfCheckouts.result].find()
{ "_id" : null, "value" : 430 }
Sum(checkout)
                                  Persistent Collection
> db.tickets.mapReduce(map, reduce, { “out”: “sumOfCheckouts” })

> db.getCollectionNames()
[
  “sumOfCheckouts”,
  "tickets",
  "tmp.mr.mapreduce_1263717818_4"
]

> db.sumOfCheckouts.find()
{ "_id" : null, "value" : 430 }

> db.sumOfCheckouts.findOne().value
430
Sum(checkout)
                                    Reduce by Group
# GROUP AS MAP/REDUCE ALTERNATIVE

> db.tickets.group({
... "initial": { "sum": 0 },
... "reduce": function(ticket, checkouts) {
...... checkouts.sum += ticket.checkout
...... }
... })
[ { "sum" : 430 } ]
Sum(checkout) Group By day




   {                      {                      {                      {
       "id": 1,               "id": 2,               "id": 3,               "id": 4,
       "day": 20100123,       "day": 20100124,       "day": 20100123,       "day": 20100124,
       "checkout": 100        "checkout": 42         "checkout": 215        "checkout": 73
   }                      }                      }                      }
Map: emit(day,checkout)




 “20100123”:100         “20100124”:42          “20100123”:215         “20100124”:73




 {                      {                      {                      {
     "id": 1,               "id": 2,               "id": 3,               "id": 4,
     "day": 20100123,       "day": 20100124,       "day": 20100123,       "day": 20100124,
     "checkout": 100        "checkout": 42         "checkout": 215        "checkout": 73
 }                      }                      }                      }
Reduce: sum(checkouts)


                  “20100123”:315




 “20100123”:100         “20100124”:42          “20100123”:215         “20100124”:73




 {                      {                      {                      {
     "id": 1,               "id": 2,               "id": 3,               "id": 4,
     "day": 20100123,       "day": 20100124,       "day": 20100123,       "day": 20100124,
     "checkout": 100        "checkout": 42         "checkout": 215        "checkout": 73
 }                      }                      }                      }
Reduce: sum(checkouts)


                  “20100123”:315                        “20100124”:115




 “20100123”:100         “20100124”:42          “20100123”:215         “20100124”:73




 {                      {                      {                      {
     "id": 1,               "id": 2,               "id": 3,               "id": 4,
     "day": 20100123,       "day": 20100124,       "day": 20100123,       "day": 20100124,
     "checkout": 100        "checkout": 42         "checkout": 215        "checkout": 73
 }                      }                      }                      }
Sum(checkout)
 Group By day
Sum(checkout)
 Group By day
Design Documents are
          Documents
Design Documents are
          Documents
Non trivial Map:
Calculate Checkout
Non trivial Map:
Calculate Checkout
Non trivial Map:
Calculate Checkout
Structured Keys and
       Group Levels
Structured Keys and
       Group Levels
Structured Keys and
       Group Levels
Structured Keys and
       Group Levels
Structured Keys and
       Group Levels
Structured Keys and
       Group Levels
Structured Keys and
       Group Levels
Sum(Checkout) by day
                            Update In-Place
> db.tickets.update({ "_id": 1 }, {
... $set: { "products": {
...... "apple": { "quantity": 5, "price": 10 },
...... "kiwi": { "quantity": 2, "price": 25 }
...... }
... },
... $unset: { "checkout": 1 }
... })

> db.tickets.find()
{ "_id" : 1, "day" : 20100123, "products" : {
   "apple" : { "quantity" : 5, "price" : 10 },
   "kiwi" : { "quantity" : 2, "price" : 25 }
}}
{ "_id" : 2, "day" : 20100123, "checkout" : 42 }
{ "_id" : 3, "day" : 20100123, "checkout" : 215 }
{ "_id" : 4, "day" : 20100123, "checkout" : 73 }
Sum(Checkout) by day
                         Calculate Checkout
> db.tickets.find()
{ "_id" : 1, "day" : 20100123, "products" : {
  "apple" : { "quantity" : 5, "price" : 10 },
  "kiwi" : { "quantity" : 2, "price" : 25 } } }

{ "_id" : 2, "day" : 20100124, "products" : {
  "banana" : { "quantity" : 2, "price" : 20 } } }

{ "_id" : 3, "day" : 20100123, "products" : {
  "kiwi" : { "quantity" : 4, "price" : 25 },
  "babana" : { "quantity" : 5, "price" : 20 },
  "lemon" : { "quantity" : 3, "price" : 5 } } }

{ "_id" : 4, "day" : 20100124, "products" : {
  "kiwi" : { "quantity" : 2, "price" : 25 },
  "babana" : { "quantity" : 1, "price" : 20 } } }
Sum(Checkout) by day
                         Calculate Checkout
> var map = function() {
... var checkout = 0
... for (var name in this.products) {
...... var product = this.products[name]
...... checkout += product.quantity * product.price
...... }
... emit(this.day, checkout)
}

> var reduce = function(key, values) {
... var sum = 0
... for (var index in values) sum += values[index]
... return sum
}
Sum(Checkout) by day
                         Calculate Checkout
> db.tickets.mapReduce(map, reduce, { "out": "sumOfCheckouts" })

> db.sumOfCheckouts.find()
{ "_id" : 20100123, "value" : 315 }
{ "_id" : 20100124, "value" : 110 }
Sum(Checkout) by day
                           Data Normalization
> db.tickets.find()
{ "_id" : 1, "day" : 20100123, "products"   : {
  "apple" : 5, "kiwi" : 2 } }
{ "_id" : 2, "day" : 20100124, "products"   : {
  "banana" : 2 } }
{ "_id" : 3, "day" : 20100123, "products"   : {
  "kiwi" : 4, "banana" : 5, "lemon" : 3 }   }
{ "_id" : 4, "day" : 20100124, "products"   : {
  "kiwi" : 2, "banana" : 1 } }

>   db.product.find()
{   "_id" : "apple", "price" : 10 }
{   "_id" : "kiwi", "price" : 25 }
{   "_id" : "banana", "price" : 20 }
{   "_id" : "lemon", "price" : 5 }
Sum(Checkout) by day
                         Data Normalization
> var map = function() {
... var checkout = 0
... for (var name in this.products) {
...... var quantity = this.products[name]
...... var price = db.product.findOne({ "_id": name }).price
...... checkout += quantity * price
...... }
... emit(this.day, checkout)
}

> var reduce = function(key, values) {
... var sum = 0
... for (var index in values) sum += values[index]
... return sum
}
Sum(Checkout) by day
                         Data Normalization
> db.tickets.mapReduce(map, reduce, { "out": "sumOfCheckouts" })

> db.sumOfCheckouts.find()
{ "_id" : 20100123, "value" : 315 }
{ "_id" : 20100124, "value" : 110 }
Count of unique
                                                  elements?
>   db.view.find();
{   "user" : "001",   "page"   :   "example.com/001",   "time"   :   2 }
{   "user" : "001",   "page"   :   "example.com/002",   "time"   :   4 }
{   "user" : "002",   "page"   :   "example.com/001",   "time"   :   6 }
{   "user" : "002",   "page"   :   "example.com/002",   "time"   :   10 }
{   "user" : "002",   "page"   :   "example.com/002",   "time"   :   12 }
{   "user" : "002",   "page"   :   "example.com/003",   "time"   :   1 }
{   "user" : "003",   "page"   :   "example.com/001",   "time"   :   42 }
{   "user" : "003",   "page"   :   "example.com/001",   "time"   :   9 }

# USER NAVIGATION SURVEY = FOR EACH USER
  # NUMBER OF UNIQUE PAGES
  # AVERAGE TIME ON A PAGE
Count of unique
                                          elements?
> var map = function() {
... var accumulator = {
...... "numberOfViews": 1,
...... "visitedPages": {},
...... "totalTime": 0
...... };

... accumulator["visitedPages"][this.page] = 1
... accumulator["totalTime"] += this.time
... emit(this.user, accumulator)
}
Count of unique
                                             elements?
# EASY TO DEBUG

> var aUser = db.view.findOne({ "user": "001" })

> var emit = function(id, value) { print(tojson(value)) }

> map.call(aUser)
{
        "numberOfViews" : 1,
        "visitedPages" : {
                "example.com/001" : 1
        },
        "totalTime" : 2
}
Count of unique
                                                  elements?
> var reduce = function(key, values) {
... var accumulator = {
...... "numberOfViews": 0,
...... "visitedPages": {},
...... "totalTime": 0
...... };

... values.forEach(function(value) {
...... accumulator["numberOfViews"] += value["numberOfViews"]
...... accumulator["totalTime"] += value["totalTime"]

...... for (var page in value["visitedPages"]) {
......... if (accumulator["visitedPages"][page] === undefined) {
............ accumulator["visitedPages"][page] = 0
......... }
......... accumulator["visitedPages"][page] += 1
...... }
... })

... return accumulator
}
Count of unique
                                            elements?
> db.view.mapReduce(map, reduce,
  { "out": "userNavigationSurvey" })

# NOT AS WE WANTED

> db.userNavigationSurvey.find()
{ "_id" : "001", "value" : {
  "numberOfViews" : 2,
  "visitedPages" : {
    "example.com/001" : 1,
    "example.com/002" : 1 },
  "totalTime" : 6 } }

{ "_id" : "002", "value" : {
  "numberOfViews" : 4,
  "visitedPages" : {
    ...
Count of unique
                                          elements?
> var finalize = function(key, accumulator) {
... accumulator["averageTime"] =
...... accumulator["totalTime"] / accumulator["numberOfViews"]
... accumulator["numberOfUniquePages"] = 0
... for (var page in accumulator["visitedPages"]) {
...... accumulator["numberOfUniquePages"] += 1
... }
... delete accumulator["totalTime"]
... delete accumulator["numberOfViews"]
... delete accumulator["visitedPages"]
... return accumulator
}
Count of unique
                                          elements?
> db.view.mapReduce(map, reduce, {
... "finalize": finalize,
... "out": "userNavigationSurvey"
})

> db.userNavigationSurvey.find()
{ "_id" : "001", "value" : {
  "averageTime" : 3, "numberOfUniquePages" : 2 } }

{ "_id" : "002", "value" : {
  "averageTime" : 7.25, "numberOfUniquePages" : 3 } }

{ "_id" : "003", "value" : {
  "averageTime" : 25.5, "numberOfUniquePages" : 1 } }
Count of unique
                                       elements by steps
# STEP 1: CREATE THE BASE COLLECTION (WITHOUT UNIQUE ELEMENTS)

> var mapBase = function() {
... emit(this.user, {
...... "numberOfViews": 1,
...... "totalTime": this.time
... })
}

> var reduceBase = function(key, values) {
... var accumulator = {
...... "numberOfViews": 0,
...... "totalTime": 0
... };
... values.forEach(function(value) {
...... accumulator["numberOfViews"] += value["numberOfViews"]
...... accumulator["totalTime"] += value["totalTime"]
... })
... return accumulator
}
Count of unique
                                         elements by steps
> var finalizeBase = function(key, accumulator) {
... accumulator["numberOfUniquePages"] = 0
... accumulator["averageTime"] =
...... accumulator["totalTime"] / accumulator["numberOfViews"]
... delete accumulator["totalTime"]
... delete accumulator["numberOfViews"]
... return accumulator
}

> db.view.mapReduce(mapBase, reduceBase, {
   "finalize": finalizeBase,
   "out": "userNavigationSurvey"
})

>   db.userNavigationSurvey.find()
{   "_id" : "001", "value" : { "numberOfUniquePages" : 0, "averageTime" : 3 } }
{   "_id" : "002", "value" : { "numberOfUniquePages" : 0, "averageTime" : 7.25 } }
{   "_id" : "003", "value" : { "numberOfUniquePages" : 0, "averageTime" : 25.5 } }
Count of unique
                                          elements by steps
# STEP 2: CREATE THE COLLECTION OF UNIQUE ELEMENTS

> var mapUniquePages = function() {
... emit(this.user + "-" + this.page, {
...... "user": this.user,
...... "page": this.page
... })
}

> var reduceUniquePages = function(key, values) {
... return values[0]
}

> db.view.mapReduce(mapUniquePages, reduceUniquePages {
   "out": "userUniquePages"
})
Count of unique
                                       elements by steps
> db.userUniquePages.find()

{ "_id" : "001-example.com/001", "value" : {
   "user" : "001", "page" : "example.com/001" } }

{ "_id" : "001-example.com/002", "value" : {
   "user" : "001", "page" : "example.com/002" } }

{ "_id" : "002-example.com/001", "value" : {
   "user" : "002", "page" : "example.com/001" } }

{ "_id" : "002-example.com/002", "value" : {
   "user" : "002", "page" : "example.com/002" } }

{ "_id" : "002-example.com/003", "value" : {
   "user" : "002", "page" : "example.com/003" } }

{ "_id" : "003-example.com/001", "value" : {
   "user" : "003", "page" : "example.com/001" } }
Count of unique
                                         elements by steps
# STEP 3: UPDATE BASE COLLECTION WITH UNIQUE ELEMENTS COUNT

> db.userUniquePages.find().forEach(function(userUniquePage) {
        db.userNavigationSurvey.update(
                { "_id": userUniquePage.value.user },
                { $inc: { "value.numberOfUniquePages": 1 } }
        )
})

>   db.userNavigationSurvey.find()
{   "_id" : "001", "value" : { "numberOfUniquePages" : 2, "averageTime" : 3 } }
{   "_id" : "002", "value" : { "numberOfUniquePages" : 3, "averageTime" : 7.25 } }
{   "_id" : "003", "value" : { "numberOfUniquePages" : 1, "averageTime" : 25.5 } }
Architecture

          Webmachine




HTTP




             HTTP


 HTTP
Scalability

        Webmachine




Nginx




                         Master/Master

        Webmachine
User Account
Message
Received by <account>
                          After <timestamp>?

function(document) {
    if (document.from && document.to) {
        var key = [ document.to, document.timestamp ]
        var content = document._attachments["content"]
        var outline = {
            "id": document._id,
            "from": document.from,
            "timestamp": document.timestamp,
            "type": content["content_type"],
            "length": content["length"],
        }
        emit(key, outline)
    }
}
Received by <account>
  After <timestamp>?
Received by <account>
                               After <timestamp>?

> curl -X GET ".../mercurio/_design/message/_view/received_after"

{ "total_rows":3, "offset":0, "rows": [
    {
        "id": "ff35356344ee0e9928c212b52e36e6f3",
        "key": [ "gabriele", 1263655442 ],
        "value": {
            "id": "ff35356344ee0e9928c212b52e36e6f3",
            "from": "chiara",
            "timestamp": 1263655442,
            "type": "text/plain;charset=utf-8",
            "length": 16
        }
    },
    ...
}
Results are
                                      ordered by Key
{ "key": [ "chiara", 126 ],
  "value": {
    "id": "ff35356344ee0e992...",
    "from": "gabriele"               [ "chiara", 126 ]
  }



                                         ==       <
}



{ "key": [ "chiara", 128 ],
  "value": {
    "id": "0deff99666425bacc...",    [ "chiara", 128 ]
    "from": "gabriele"
  }


                                          <
}



{ "key": [ "gabriele", 120 ],
  "value": {
    "id": "9842063609746c661...",   [ "gabriele", 120 ]
    "from": "chiara"
  }
}
Select with Key

{ "key": [ "chiara", 126 ],
  "value": {
    "id": "ff35356344ee0e992...",
                                    received_after?
  }
    "from": "gabriele"
                                      key=["chiara",126]
}



{ "key": [ "chiara", 128 ],
  "value": {
    "id": "0deff99666425bacc...",
    "from": "gabriele"
  }
}



{ "key": [ "gabriele", 120 ],
  "value": {
    "id": "9842063609746c661...",
    "from": "chiara"
  }
}
Select with range of Keys

{ "key": [ "chiara", 126 ],         received_after?
  "value": {
    "id": "ff35356344ee0e992...",
    "from": "gabriele"
                                      startkey=["chiara",126]&
}
  }
                                      endkey=["gabriele",0]

{ "key": [ "chiara", 128 ],
  "value": {
    "id": "0deff99666425bacc...",
    "from": "gabriele"
  }
}



{ "key": [ "gabriele", 120 ],
  "value": {
    "id": "9842063609746c661...",
    "from": "chiara"
  }
}
Select with range of Keys

{ "key": [ "chiara", 126 ],
  "value": {
    "id": "ff35356344ee0e992...",
    "from": "gabriele"
  }
}
                                     [ "chiara", [] ]

{ "key": [ "chiara", 128 ],
  "value": {
    "id": "0deff99666425bacc...",
    "from": "gabriele"
  }
                                    { "key": [ "chiara", [] ],
}
                                      "value": {
                                        "id": "0deff99666425bacc...",
                                        "from": "gabriele"
{ "key": [ "gabriele", 120 ],         }
  "value": {                        }
    "id": "9842063609746c661...",
    "from": "chiara"
  }
}
Select with range of Keys

{ "key": [ "chiara", 126 ],         received_after?
  "value": {
    "id": "ff35356344ee0e992...",
    "from": "gabriele"
                                      startkey=["chiara",126]&
}
  }
                                      endkey=["chiara",[]]

{ "key": [ "chiara", 128 ],
  "value": {
    "id": "0deff99666425bacc...",
    "from": "gabriele"
  }
}



{ "key": [ "gabriele", 120 ],
  "value": {
    "id": "9842063609746c661...",
    "from": "chiara"
  }
}
Received by “chiara”
                                              After 126
{ "key": [ "chiara", 126 ],         received_after?
  "value": {
    "id": "ff35356344ee0e992...",
    "from": "gabriele"
                                      startkey=["chiara",127]&
}
  }
                                      endkey=["chiara",[]]

{ "key": [ "chiara", 128 ],
  "value": {
    "id": "0deff99666425bacc...",
    "from": "gabriele"
  }
}



{ "key": [ "gabriele", 120 ],
  "value": {
    "id": "9842063609746c661...",
    "from": "chiara"
  }
}
Push Received
             Messages from Server



Check for Messages           _changes?
  received by <account.id>     filter=message/received&
  after <timestamp>            by=<account.id>&
                               after=<timestamp>

     Send Message               Save Document
     to <account.id>              to: <account.id>
Push Received
                         Messages from Server

_changes?filter=message/received&by=<account.id>&after=<timestamp>



    function(document, request) {
        var receivedByMe =
            document.to === request.query.by

        var receivedAfterLastTime =
            document.receivedAt >= request.query.after

        return receivedByMe && receivedAfterLastTime
    }
Backoffice as
Couch Application

Más contenido relacionado

La actualidad más candente

Lecture 1 (distributed systems)
Lecture 1 (distributed systems)Lecture 1 (distributed systems)
Lecture 1 (distributed systems)Fazli Amin
 
Scalability
ScalabilityScalability
Scalabilityfelho
 
cloud computing, Principle and Paradigms: 1 introdution
cloud computing, Principle and Paradigms: 1 introdutioncloud computing, Principle and Paradigms: 1 introdution
cloud computing, Principle and Paradigms: 1 introdutionMajid Hajibaba
 
Cloud computing
Cloud computingCloud computing
Cloud computingstudent
 
Lecture 6: IoT Data Processing
Lecture 6: IoT Data Processing Lecture 6: IoT Data Processing
Lecture 6: IoT Data Processing PayamBarnaghi
 
cloud computing:Types of virtualization
cloud computing:Types of virtualizationcloud computing:Types of virtualization
cloud computing:Types of virtualizationDr.Neeraj Kumar Pandey
 
Common MongoDB Use Cases
Common MongoDB Use CasesCommon MongoDB Use Cases
Common MongoDB Use CasesDATAVERSITY
 
Presentation on Databases in the Cloud
Presentation on Databases in the CloudPresentation on Databases in the Cloud
Presentation on Databases in the Cloudmoshfiq
 
Cloud computing ppt
Cloud computing pptCloud computing ppt
Cloud computing pptJagriti Rai
 
Distributed data processing
Distributed data processingDistributed data processing
Distributed data processingAyisha Kowsar
 
Cloud Architecture in the Data Center
Cloud Architecture in the Data CenterCloud Architecture in the Data Center
Cloud Architecture in the Data CenterInterVision Systems
 

La actualidad más candente (20)

Cluster computing
Cluster computingCluster computing
Cluster computing
 
DBSCAN (1) (4).pptx
DBSCAN (1) (4).pptxDBSCAN (1) (4).pptx
DBSCAN (1) (4).pptx
 
cluster computing
cluster computingcluster computing
cluster computing
 
Data Link Layer| Error Detection
Data Link Layer| Error DetectionData Link Layer| Error Detection
Data Link Layer| Error Detection
 
Lecture 1 (distributed systems)
Lecture 1 (distributed systems)Lecture 1 (distributed systems)
Lecture 1 (distributed systems)
 
Hadoop Architecture
Hadoop ArchitectureHadoop Architecture
Hadoop Architecture
 
Association rules
Association rulesAssociation rules
Association rules
 
Nosql databases
Nosql databasesNosql databases
Nosql databases
 
Cluster computing
Cluster computingCluster computing
Cluster computing
 
Cloud sim
Cloud simCloud sim
Cloud sim
 
Scalability
ScalabilityScalability
Scalability
 
cloud computing, Principle and Paradigms: 1 introdution
cloud computing, Principle and Paradigms: 1 introdutioncloud computing, Principle and Paradigms: 1 introdution
cloud computing, Principle and Paradigms: 1 introdution
 
Cloud computing
Cloud computingCloud computing
Cloud computing
 
Lecture 6: IoT Data Processing
Lecture 6: IoT Data Processing Lecture 6: IoT Data Processing
Lecture 6: IoT Data Processing
 
cloud computing:Types of virtualization
cloud computing:Types of virtualizationcloud computing:Types of virtualization
cloud computing:Types of virtualization
 
Common MongoDB Use Cases
Common MongoDB Use CasesCommon MongoDB Use Cases
Common MongoDB Use Cases
 
Presentation on Databases in the Cloud
Presentation on Databases in the CloudPresentation on Databases in the Cloud
Presentation on Databases in the Cloud
 
Cloud computing ppt
Cloud computing pptCloud computing ppt
Cloud computing ppt
 
Distributed data processing
Distributed data processingDistributed data processing
Distributed data processing
 
Cloud Architecture in the Data Center
Cloud Architecture in the Data CenterCloud Architecture in the Data Center
Cloud Architecture in the Data Center
 

Similar a CouchDB Vs MongoDB

Apéro RubyBdx - MongoDB - 8-11-2011
Apéro RubyBdx - MongoDB - 8-11-2011Apéro RubyBdx - MongoDB - 8-11-2011
Apéro RubyBdx - MongoDB - 8-11-2011pierrerenaudin
 
Living in eventually consistent reality
Living in eventually consistent realityLiving in eventually consistent reality
Living in eventually consistent realityBartosz Sypytkowski
 
MongoDB for Time Series Data Part 2: Analyzing Time Series Data Using the Agg...
MongoDB for Time Series Data Part 2: Analyzing Time Series Data Using the Agg...MongoDB for Time Series Data Part 2: Analyzing Time Series Data Using the Agg...
MongoDB for Time Series Data Part 2: Analyzing Time Series Data Using the Agg...MongoDB
 
MongoDB Analytics
MongoDB AnalyticsMongoDB Analytics
MongoDB Analyticsdatablend
 
Powering Heap With PostgreSQL And CitusDB (PGConf Silicon Valley 2015)
Powering Heap With PostgreSQL And CitusDB (PGConf Silicon Valley 2015)Powering Heap With PostgreSQL And CitusDB (PGConf Silicon Valley 2015)
Powering Heap With PostgreSQL And CitusDB (PGConf Silicon Valley 2015)Dan Robinson
 
MongoDB for Time Series Data: Analyzing Time Series Data Using the Aggregatio...
MongoDB for Time Series Data: Analyzing Time Series Data Using the Aggregatio...MongoDB for Time Series Data: Analyzing Time Series Data Using the Aggregatio...
MongoDB for Time Series Data: Analyzing Time Series Data Using the Aggregatio...MongoDB
 
Detection of errors and potential vulnerabilities in C and C++ code using the...
Detection of errors and potential vulnerabilities in C and C++ code using the...Detection of errors and potential vulnerabilities in C and C++ code using the...
Detection of errors and potential vulnerabilities in C and C++ code using the...Andrey Karpov
 

Similar a CouchDB Vs MongoDB (7)

Apéro RubyBdx - MongoDB - 8-11-2011
Apéro RubyBdx - MongoDB - 8-11-2011Apéro RubyBdx - MongoDB - 8-11-2011
Apéro RubyBdx - MongoDB - 8-11-2011
 
Living in eventually consistent reality
Living in eventually consistent realityLiving in eventually consistent reality
Living in eventually consistent reality
 
MongoDB for Time Series Data Part 2: Analyzing Time Series Data Using the Agg...
MongoDB for Time Series Data Part 2: Analyzing Time Series Data Using the Agg...MongoDB for Time Series Data Part 2: Analyzing Time Series Data Using the Agg...
MongoDB for Time Series Data Part 2: Analyzing Time Series Data Using the Agg...
 
MongoDB Analytics
MongoDB AnalyticsMongoDB Analytics
MongoDB Analytics
 
Powering Heap With PostgreSQL And CitusDB (PGConf Silicon Valley 2015)
Powering Heap With PostgreSQL And CitusDB (PGConf Silicon Valley 2015)Powering Heap With PostgreSQL And CitusDB (PGConf Silicon Valley 2015)
Powering Heap With PostgreSQL And CitusDB (PGConf Silicon Valley 2015)
 
MongoDB for Time Series Data: Analyzing Time Series Data Using the Aggregatio...
MongoDB for Time Series Data: Analyzing Time Series Data Using the Aggregatio...MongoDB for Time Series Data: Analyzing Time Series Data Using the Aggregatio...
MongoDB for Time Series Data: Analyzing Time Series Data Using the Aggregatio...
 
Detection of errors and potential vulnerabilities in C and C++ code using the...
Detection of errors and potential vulnerabilities in C and C++ code using the...Detection of errors and potential vulnerabilities in C and C++ code using the...
Detection of errors and potential vulnerabilities in C and C++ code using the...
 

Más de Gabriele Lana

Microservice Architectures
Microservice ArchitecturesMicroservice Architectures
Microservice ArchitecturesGabriele Lana
 
Professional Programmer 2018
Professional Programmer 2018Professional Programmer 2018
Professional Programmer 2018Gabriele Lana
 
Parse Everything With Elixir
Parse Everything With ElixirParse Everything With Elixir
Parse Everything With ElixirGabriele Lana
 
Professional Programmer (3 Years Later)
Professional Programmer (3 Years Later)Professional Programmer (3 Years Later)
Professional Programmer (3 Years Later)Gabriele Lana
 
Resource Oriented Design
Resource Oriented DesignResource Oriented Design
Resource Oriented DesignGabriele Lana
 
Agileday Coderetreat 2013
Agileday Coderetreat 2013Agileday Coderetreat 2013
Agileday Coderetreat 2013Gabriele Lana
 
Milano Legacy Coderetreat 2013
Milano Legacy Coderetreat 2013Milano Legacy Coderetreat 2013
Milano Legacy Coderetreat 2013Gabriele Lana
 
Minimum Viable Product
Minimum Viable ProductMinimum Viable Product
Minimum Viable ProductGabriele Lana
 
Professional Programmer
Professional ProgrammerProfessional Programmer
Professional ProgrammerGabriele Lana
 
It is not supposed to fly but it does
It is not supposed to fly but it doesIt is not supposed to fly but it does
It is not supposed to fly but it doesGabriele Lana
 
Introduction to Nodejs
Introduction to NodejsIntroduction to Nodejs
Introduction to NodejsGabriele Lana
 
Nodejs Explained with Examples
Nodejs Explained with ExamplesNodejs Explained with Examples
Nodejs Explained with ExamplesGabriele Lana
 

Más de Gabriele Lana (20)

Microservice Architectures
Microservice ArchitecturesMicroservice Architectures
Microservice Architectures
 
Professional Programmer 2018
Professional Programmer 2018Professional Programmer 2018
Professional Programmer 2018
 
Beyond Phoenix
Beyond PhoenixBeyond Phoenix
Beyond Phoenix
 
Parse Everything With Elixir
Parse Everything With ElixirParse Everything With Elixir
Parse Everything With Elixir
 
The Magic Of Elixir
The Magic Of ElixirThe Magic Of Elixir
The Magic Of Elixir
 
Professional Programmer (3 Years Later)
Professional Programmer (3 Years Later)Professional Programmer (3 Years Later)
Professional Programmer (3 Years Later)
 
Resource Oriented Design
Resource Oriented DesignResource Oriented Design
Resource Oriented Design
 
Agileday Coderetreat 2013
Agileday Coderetreat 2013Agileday Coderetreat 2013
Agileday Coderetreat 2013
 
Milano Legacy Coderetreat 2013
Milano Legacy Coderetreat 2013Milano Legacy Coderetreat 2013
Milano Legacy Coderetreat 2013
 
Minimum Viable Product
Minimum Viable ProductMinimum Viable Product
Minimum Viable Product
 
API Over HTTP
API Over HTTPAPI Over HTTP
API Over HTTP
 
coderetreat
coderetreatcoderetreat
coderetreat
 
Professional Programmer
Professional ProgrammerProfessional Programmer
Professional Programmer
 
It is not supposed to fly but it does
It is not supposed to fly but it doesIt is not supposed to fly but it does
It is not supposed to fly but it does
 
Introduction to Nodejs
Introduction to NodejsIntroduction to Nodejs
Introduction to Nodejs
 
MongoDB With Style
MongoDB With StyleMongoDB With Style
MongoDB With Style
 
Nosql
NosqlNosql
Nosql
 
Magic of Ruby
Magic of RubyMagic of Ruby
Magic of Ruby
 
Nodejs Explained with Examples
Nodejs Explained with ExamplesNodejs Explained with Examples
Nodejs Explained with Examples
 
Why couchdb is cool
Why couchdb is coolWhy couchdb is cool
Why couchdb is cool
 

Último

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
 
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
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Igalia
 
🐬 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
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsJoaquim Jorge
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CVKhem
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEarley Information Science
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...Neo4j
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processorsdebabhi2
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfsudhanshuwaghmare1
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?Igalia
 
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
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessPixlogix Infotech
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 

Último (20)

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
 
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
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
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
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your Business
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 

CouchDB Vs MongoDB

  • 1. VS
  • 6. Document { "day": [ 2010, 01, 23 ], "products": { "apple": { "price": 10 Key -> "quantity": 6 }, "kiwi": { "price": 20 "quantity": 2 } }, "checkout": 100 }
  • 7. Couchdb Mongodb Data Model Document-Oriented (JSON) Document-Oriented (BSON) Interface HTTP/REST Custom protocol over TCP/IP Object Database contains Collections Database contains Documents Storage Collections contains Documents Map/Reduce (javascript) creating Query Map/Reduce (javascript + others) Collections + Object-Based query Method creating Views + Range queries language Master-Master with custom Replication Master-Slave conflict resolution functions MVCC (Multi Version Concurrency Concurrency Update in-place Control) Written In Erlang C++
  • 9. Example: Tickets { { { { "id": 1, "id": 2, "id": 3, "id": 4, "day": 20100123, "day": 20100123, "day": 20100123, "day": 20100123, "checkout": 100 "checkout": 42 "checkout": 215 "checkout": 73 } } } }
  • 10. Sum(checkout)? { { { { "id": 1, "id": 2, "id": 3, "id": 4, "day": 20100123, "day": 20100123, "day": 20100123, "day": 20100123, "checkout": 100 "checkout": 42 "checkout": 215 "checkout": 73 } } } }
  • 11. Map: emit(checkout) 100 42 215 73 { { { { "id": 1, "id": 2, "id": 3, "id": 4, "day": 20100123, "day": 20100123, "day": 20100123, "day": 20100123, "checkout": 100 "checkout": 42 "checkout": 215 "checkout": 73 } } } }
  • 12. Reduce: sum(checkouts) 142 288 100 42 215 73 { { { { "id": 1, "id": 2, "id": 3, "id": 4, "day": 20100123, "day": 20100123, "day": 20100123, "day": 20100123, "checkout": 100 "checkout": 42 "checkout": 215 "checkout": 73 } } } }
  • 13. Reduce: sum(checkouts) 430 142 288 100 42 215 73 { { { { "id": 1, "id": 2, "id": 3, "id": 4, "day": 20100123, "day": 20100123, "day": 20100123, "day": 20100123, "checkout": 100 "checkout": 42 "checkout": 215 "checkout": 73 } } } }
  • 14. Reduce must be associative reduce( 100 42 215 73 ) == 430 Must be equal to reduce( reduce( 100 42 ) == 142 reduce( 215 73 ) == 288 ) == 430
  • 16. Inherently distributed 430 142 288 100 42 215 73 { { { { "id": 1, "id": 2, "id": 3, "id": 4, "day": 20100123, "day": 20100123, "day": 20100123, "day": 20100123, "checkout": 100 "checkout": 42 "checkout": 215 "checkout": 73 } } } }
  • 17. Logaritmic Update 430 142 288 100 42 215 73 { { { { "id": 1, "id": 2, "id": 3, "id": 4, "day": 20100123, "day": 20100123, "day": 20100123, "day": 20100123, "checkout": 100 "checkout": 42 "checkout": 210 "checkout": 73 } } } }
  • 18. Logaritmic Update 430 142 288 100 42 210 73 { { { { "id": 1, "id": 2, "id": 3, "id": 4, "day": 20100123, "day": 20100123, "day": 20100123, "day": 20100123, "checkout": 100 "checkout": 42 "checkout": 210 "checkout": 73 } } } }
  • 19. Logaritmic Update 430 142 283 100 42 210 73 { { { { "id": 1, "id": 2, "id": 3, "id": 4, "day": 20100123, "day": 20100123, "day": 20100123, "day": 20100123, "checkout": 100 "checkout": 42 "checkout": 210 "checkout": 73 } } } }
  • 20. Logaritmic Update 425 142 283 100 42 210 73 { { { { "id": 1, "id": 2, "id": 3, "id": 4, "day": 20100123, "day": 20100123, "day": 20100123, "day": 20100123, "checkout": 100 "checkout": 42 "checkout": 210 "checkout": 73 } } } }
  • 26. Sum(checkout) # START SERVER $ ~/opt/mongodb-1.3.0/bin/mongod --dbpath=./db/mongodb.01/ --logpath=./log/mongodb.01 --port 30001 # START SHELL $ ~/opt/mongodb-1.3.0/bin/mongo localhost:30001 connecting to: localhost:30001/test type "help" for help > show dbs admin local
  • 27. Sum(checkout) > use checkout switched to db checkout > db.tickets.save({ "_id": 1, "day": 20100123, "checkout": 100 }) > db.tickets.save({ "_id": 2, "day": 20100123, "checkout": 42 }) > db.tickets.save({ "_id": 3, "day": 20100123, "checkout": 215 }) > db.tickets.save({ "_id": 4, "day": 20100123, "checkout": 73 }) > db.tickets.count() 4 > db.tickets.find() { "_id" : 1, "day" : 20100123, "checkout" : 100 } ... > db.tickets.find({ "_id": 1 }) { "_id" : 1, "day" : 20100123, "checkout" : 100 }
  • 28. Sum(checkout) > var map = function() { ... emit(null, this.checkout) ... } > var reduce = function(key, values) { ... var sum = 0 ... for (var index in values) sum += values[index] ... return sum ... }
  • 29. Sum(checkout) Temporary Collection > sumOfCheckouts = db.tickets.mapReduce(map, reduce) { "result" : "tmp.mr.mapreduce_1263717818_4", "timeMillis" : 8, "counts" : { "input" : 4, "emit" : 4, "output" : 1 }, "ok" : 1 } > db.getCollectionNames() [ "tickets", "tmp.mr.mapreduce_1263717818_4", ] > db[sumOfCheckouts.result].find() { "_id" : null, "value" : 430 }
  • 30. Sum(checkout) Persistent Collection > db.tickets.mapReduce(map, reduce, { “out”: “sumOfCheckouts” }) > db.getCollectionNames() [ “sumOfCheckouts”, "tickets", "tmp.mr.mapreduce_1263717818_4" ] > db.sumOfCheckouts.find() { "_id" : null, "value" : 430 } > db.sumOfCheckouts.findOne().value 430
  • 31. Sum(checkout) Reduce by Group # GROUP AS MAP/REDUCE ALTERNATIVE > db.tickets.group({ ... "initial": { "sum": 0 }, ... "reduce": function(ticket, checkouts) { ...... checkouts.sum += ticket.checkout ...... } ... }) [ { "sum" : 430 } ]
  • 32. Sum(checkout) Group By day { { { { "id": 1, "id": 2, "id": 3, "id": 4, "day": 20100123, "day": 20100124, "day": 20100123, "day": 20100124, "checkout": 100 "checkout": 42 "checkout": 215 "checkout": 73 } } } }
  • 33. Map: emit(day,checkout) “20100123”:100 “20100124”:42 “20100123”:215 “20100124”:73 { { { { "id": 1, "id": 2, "id": 3, "id": 4, "day": 20100123, "day": 20100124, "day": 20100123, "day": 20100124, "checkout": 100 "checkout": 42 "checkout": 215 "checkout": 73 } } } }
  • 34. Reduce: sum(checkouts) “20100123”:315 “20100123”:100 “20100124”:42 “20100123”:215 “20100124”:73 { { { { "id": 1, "id": 2, "id": 3, "id": 4, "day": 20100123, "day": 20100124, "day": 20100123, "day": 20100124, "checkout": 100 "checkout": 42 "checkout": 215 "checkout": 73 } } } }
  • 35. Reduce: sum(checkouts) “20100123”:315 “20100124”:115 “20100123”:100 “20100124”:42 “20100123”:215 “20100124”:73 { { { { "id": 1, "id": 2, "id": 3, "id": 4, "day": 20100123, "day": 20100124, "day": 20100123, "day": 20100124, "checkout": 100 "checkout": 42 "checkout": 215 "checkout": 73 } } } }
  • 38. Design Documents are Documents
  • 39. Design Documents are Documents
  • 43. Structured Keys and Group Levels
  • 44. Structured Keys and Group Levels
  • 45. Structured Keys and Group Levels
  • 46. Structured Keys and Group Levels
  • 47. Structured Keys and Group Levels
  • 48. Structured Keys and Group Levels
  • 49. Structured Keys and Group Levels
  • 50. Sum(Checkout) by day Update In-Place > db.tickets.update({ "_id": 1 }, { ... $set: { "products": { ...... "apple": { "quantity": 5, "price": 10 }, ...... "kiwi": { "quantity": 2, "price": 25 } ...... } ... }, ... $unset: { "checkout": 1 } ... }) > db.tickets.find() { "_id" : 1, "day" : 20100123, "products" : { "apple" : { "quantity" : 5, "price" : 10 }, "kiwi" : { "quantity" : 2, "price" : 25 } }} { "_id" : 2, "day" : 20100123, "checkout" : 42 } { "_id" : 3, "day" : 20100123, "checkout" : 215 } { "_id" : 4, "day" : 20100123, "checkout" : 73 }
  • 51. Sum(Checkout) by day Calculate Checkout > db.tickets.find() { "_id" : 1, "day" : 20100123, "products" : { "apple" : { "quantity" : 5, "price" : 10 }, "kiwi" : { "quantity" : 2, "price" : 25 } } } { "_id" : 2, "day" : 20100124, "products" : { "banana" : { "quantity" : 2, "price" : 20 } } } { "_id" : 3, "day" : 20100123, "products" : { "kiwi" : { "quantity" : 4, "price" : 25 }, "babana" : { "quantity" : 5, "price" : 20 }, "lemon" : { "quantity" : 3, "price" : 5 } } } { "_id" : 4, "day" : 20100124, "products" : { "kiwi" : { "quantity" : 2, "price" : 25 }, "babana" : { "quantity" : 1, "price" : 20 } } }
  • 52. Sum(Checkout) by day Calculate Checkout > var map = function() { ... var checkout = 0 ... for (var name in this.products) { ...... var product = this.products[name] ...... checkout += product.quantity * product.price ...... } ... emit(this.day, checkout) } > var reduce = function(key, values) { ... var sum = 0 ... for (var index in values) sum += values[index] ... return sum }
  • 53. Sum(Checkout) by day Calculate Checkout > db.tickets.mapReduce(map, reduce, { "out": "sumOfCheckouts" }) > db.sumOfCheckouts.find() { "_id" : 20100123, "value" : 315 } { "_id" : 20100124, "value" : 110 }
  • 54. Sum(Checkout) by day Data Normalization > db.tickets.find() { "_id" : 1, "day" : 20100123, "products" : { "apple" : 5, "kiwi" : 2 } } { "_id" : 2, "day" : 20100124, "products" : { "banana" : 2 } } { "_id" : 3, "day" : 20100123, "products" : { "kiwi" : 4, "banana" : 5, "lemon" : 3 } } { "_id" : 4, "day" : 20100124, "products" : { "kiwi" : 2, "banana" : 1 } } > db.product.find() { "_id" : "apple", "price" : 10 } { "_id" : "kiwi", "price" : 25 } { "_id" : "banana", "price" : 20 } { "_id" : "lemon", "price" : 5 }
  • 55. Sum(Checkout) by day Data Normalization > var map = function() { ... var checkout = 0 ... for (var name in this.products) { ...... var quantity = this.products[name] ...... var price = db.product.findOne({ "_id": name }).price ...... checkout += quantity * price ...... } ... emit(this.day, checkout) } > var reduce = function(key, values) { ... var sum = 0 ... for (var index in values) sum += values[index] ... return sum }
  • 56. Sum(Checkout) by day Data Normalization > db.tickets.mapReduce(map, reduce, { "out": "sumOfCheckouts" }) > db.sumOfCheckouts.find() { "_id" : 20100123, "value" : 315 } { "_id" : 20100124, "value" : 110 }
  • 57. Count of unique elements? > db.view.find(); { "user" : "001", "page" : "example.com/001", "time" : 2 } { "user" : "001", "page" : "example.com/002", "time" : 4 } { "user" : "002", "page" : "example.com/001", "time" : 6 } { "user" : "002", "page" : "example.com/002", "time" : 10 } { "user" : "002", "page" : "example.com/002", "time" : 12 } { "user" : "002", "page" : "example.com/003", "time" : 1 } { "user" : "003", "page" : "example.com/001", "time" : 42 } { "user" : "003", "page" : "example.com/001", "time" : 9 } # USER NAVIGATION SURVEY = FOR EACH USER # NUMBER OF UNIQUE PAGES # AVERAGE TIME ON A PAGE
  • 58. Count of unique elements? > var map = function() { ... var accumulator = { ...... "numberOfViews": 1, ...... "visitedPages": {}, ...... "totalTime": 0 ...... }; ... accumulator["visitedPages"][this.page] = 1 ... accumulator["totalTime"] += this.time ... emit(this.user, accumulator) }
  • 59. Count of unique elements? # EASY TO DEBUG > var aUser = db.view.findOne({ "user": "001" }) > var emit = function(id, value) { print(tojson(value)) } > map.call(aUser) { "numberOfViews" : 1, "visitedPages" : { "example.com/001" : 1 }, "totalTime" : 2 }
  • 60. Count of unique elements? > var reduce = function(key, values) { ... var accumulator = { ...... "numberOfViews": 0, ...... "visitedPages": {}, ...... "totalTime": 0 ...... }; ... values.forEach(function(value) { ...... accumulator["numberOfViews"] += value["numberOfViews"] ...... accumulator["totalTime"] += value["totalTime"] ...... for (var page in value["visitedPages"]) { ......... if (accumulator["visitedPages"][page] === undefined) { ............ accumulator["visitedPages"][page] = 0 ......... } ......... accumulator["visitedPages"][page] += 1 ...... } ... }) ... return accumulator }
  • 61. Count of unique elements? > db.view.mapReduce(map, reduce, { "out": "userNavigationSurvey" }) # NOT AS WE WANTED > db.userNavigationSurvey.find() { "_id" : "001", "value" : { "numberOfViews" : 2, "visitedPages" : { "example.com/001" : 1, "example.com/002" : 1 }, "totalTime" : 6 } } { "_id" : "002", "value" : { "numberOfViews" : 4, "visitedPages" : { ...
  • 62. Count of unique elements? > var finalize = function(key, accumulator) { ... accumulator["averageTime"] = ...... accumulator["totalTime"] / accumulator["numberOfViews"] ... accumulator["numberOfUniquePages"] = 0 ... for (var page in accumulator["visitedPages"]) { ...... accumulator["numberOfUniquePages"] += 1 ... } ... delete accumulator["totalTime"] ... delete accumulator["numberOfViews"] ... delete accumulator["visitedPages"] ... return accumulator }
  • 63. Count of unique elements? > db.view.mapReduce(map, reduce, { ... "finalize": finalize, ... "out": "userNavigationSurvey" }) > db.userNavigationSurvey.find() { "_id" : "001", "value" : { "averageTime" : 3, "numberOfUniquePages" : 2 } } { "_id" : "002", "value" : { "averageTime" : 7.25, "numberOfUniquePages" : 3 } } { "_id" : "003", "value" : { "averageTime" : 25.5, "numberOfUniquePages" : 1 } }
  • 64.
  • 65. Count of unique elements by steps # STEP 1: CREATE THE BASE COLLECTION (WITHOUT UNIQUE ELEMENTS) > var mapBase = function() { ... emit(this.user, { ...... "numberOfViews": 1, ...... "totalTime": this.time ... }) } > var reduceBase = function(key, values) { ... var accumulator = { ...... "numberOfViews": 0, ...... "totalTime": 0 ... }; ... values.forEach(function(value) { ...... accumulator["numberOfViews"] += value["numberOfViews"] ...... accumulator["totalTime"] += value["totalTime"] ... }) ... return accumulator }
  • 66. Count of unique elements by steps > var finalizeBase = function(key, accumulator) { ... accumulator["numberOfUniquePages"] = 0 ... accumulator["averageTime"] = ...... accumulator["totalTime"] / accumulator["numberOfViews"] ... delete accumulator["totalTime"] ... delete accumulator["numberOfViews"] ... return accumulator } > db.view.mapReduce(mapBase, reduceBase, { "finalize": finalizeBase, "out": "userNavigationSurvey" }) > db.userNavigationSurvey.find() { "_id" : "001", "value" : { "numberOfUniquePages" : 0, "averageTime" : 3 } } { "_id" : "002", "value" : { "numberOfUniquePages" : 0, "averageTime" : 7.25 } } { "_id" : "003", "value" : { "numberOfUniquePages" : 0, "averageTime" : 25.5 } }
  • 67. Count of unique elements by steps # STEP 2: CREATE THE COLLECTION OF UNIQUE ELEMENTS > var mapUniquePages = function() { ... emit(this.user + "-" + this.page, { ...... "user": this.user, ...... "page": this.page ... }) } > var reduceUniquePages = function(key, values) { ... return values[0] } > db.view.mapReduce(mapUniquePages, reduceUniquePages { "out": "userUniquePages" })
  • 68. Count of unique elements by steps > db.userUniquePages.find() { "_id" : "001-example.com/001", "value" : { "user" : "001", "page" : "example.com/001" } } { "_id" : "001-example.com/002", "value" : { "user" : "001", "page" : "example.com/002" } } { "_id" : "002-example.com/001", "value" : { "user" : "002", "page" : "example.com/001" } } { "_id" : "002-example.com/002", "value" : { "user" : "002", "page" : "example.com/002" } } { "_id" : "002-example.com/003", "value" : { "user" : "002", "page" : "example.com/003" } } { "_id" : "003-example.com/001", "value" : { "user" : "003", "page" : "example.com/001" } }
  • 69. Count of unique elements by steps # STEP 3: UPDATE BASE COLLECTION WITH UNIQUE ELEMENTS COUNT > db.userUniquePages.find().forEach(function(userUniquePage) { db.userNavigationSurvey.update( { "_id": userUniquePage.value.user }, { $inc: { "value.numberOfUniquePages": 1 } } ) }) > db.userNavigationSurvey.find() { "_id" : "001", "value" : { "numberOfUniquePages" : 2, "averageTime" : 3 } } { "_id" : "002", "value" : { "numberOfUniquePages" : 3, "averageTime" : 7.25 } } { "_id" : "003", "value" : { "numberOfUniquePages" : 1, "averageTime" : 25.5 } }
  • 70. Architecture Webmachine HTTP HTTP HTTP
  • 71. Scalability Webmachine Nginx Master/Master Webmachine
  • 74. Received by <account> After <timestamp>? function(document) { if (document.from && document.to) { var key = [ document.to, document.timestamp ] var content = document._attachments["content"] var outline = { "id": document._id, "from": document.from, "timestamp": document.timestamp, "type": content["content_type"], "length": content["length"], } emit(key, outline) } }
  • 75. Received by <account> After <timestamp>?
  • 76. Received by <account> After <timestamp>? > curl -X GET ".../mercurio/_design/message/_view/received_after" { "total_rows":3, "offset":0, "rows": [ { "id": "ff35356344ee0e9928c212b52e36e6f3", "key": [ "gabriele", 1263655442 ], "value": { "id": "ff35356344ee0e9928c212b52e36e6f3", "from": "chiara", "timestamp": 1263655442, "type": "text/plain;charset=utf-8", "length": 16 } }, ... }
  • 77. Results are ordered by Key { "key": [ "chiara", 126 ], "value": { "id": "ff35356344ee0e992...", "from": "gabriele" [ "chiara", 126 ] } == < } { "key": [ "chiara", 128 ], "value": { "id": "0deff99666425bacc...", [ "chiara", 128 ] "from": "gabriele" } < } { "key": [ "gabriele", 120 ], "value": { "id": "9842063609746c661...", [ "gabriele", 120 ] "from": "chiara" } }
  • 78. Select with Key { "key": [ "chiara", 126 ], "value": { "id": "ff35356344ee0e992...", received_after? } "from": "gabriele" key=["chiara",126] } { "key": [ "chiara", 128 ], "value": { "id": "0deff99666425bacc...", "from": "gabriele" } } { "key": [ "gabriele", 120 ], "value": { "id": "9842063609746c661...", "from": "chiara" } }
  • 79. Select with range of Keys { "key": [ "chiara", 126 ], received_after? "value": { "id": "ff35356344ee0e992...", "from": "gabriele" startkey=["chiara",126]& } } endkey=["gabriele",0] { "key": [ "chiara", 128 ], "value": { "id": "0deff99666425bacc...", "from": "gabriele" } } { "key": [ "gabriele", 120 ], "value": { "id": "9842063609746c661...", "from": "chiara" } }
  • 80. Select with range of Keys { "key": [ "chiara", 126 ], "value": { "id": "ff35356344ee0e992...", "from": "gabriele" } } [ "chiara", [] ] { "key": [ "chiara", 128 ], "value": { "id": "0deff99666425bacc...", "from": "gabriele" } { "key": [ "chiara", [] ], } "value": { "id": "0deff99666425bacc...", "from": "gabriele" { "key": [ "gabriele", 120 ], } "value": { } "id": "9842063609746c661...", "from": "chiara" } }
  • 81. Select with range of Keys { "key": [ "chiara", 126 ], received_after? "value": { "id": "ff35356344ee0e992...", "from": "gabriele" startkey=["chiara",126]& } } endkey=["chiara",[]] { "key": [ "chiara", 128 ], "value": { "id": "0deff99666425bacc...", "from": "gabriele" } } { "key": [ "gabriele", 120 ], "value": { "id": "9842063609746c661...", "from": "chiara" } }
  • 82. Received by “chiara” After 126 { "key": [ "chiara", 126 ], received_after? "value": { "id": "ff35356344ee0e992...", "from": "gabriele" startkey=["chiara",127]& } } endkey=["chiara",[]] { "key": [ "chiara", 128 ], "value": { "id": "0deff99666425bacc...", "from": "gabriele" } } { "key": [ "gabriele", 120 ], "value": { "id": "9842063609746c661...", "from": "chiara" } }
  • 83. Push Received Messages from Server Check for Messages _changes? received by <account.id> filter=message/received& after <timestamp> by=<account.id>& after=<timestamp> Send Message Save Document to <account.id> to: <account.id>
  • 84. Push Received Messages from Server _changes?filter=message/received&by=<account.id>&after=<timestamp> function(document, request) { var receivedByMe = document.to === request.query.by var receivedAfterLastTime = document.receivedAt >= request.query.after return receivedByMe && receivedAfterLastTime }