SlideShare ist ein Scribd-Unternehmen logo
1 von 85
Downloaden Sie, um offline zu lesen
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

Weitere ähnliche Inhalte

Was ist angesagt?

Mastering PostgreSQL Administration
Mastering PostgreSQL AdministrationMastering PostgreSQL Administration
Mastering PostgreSQL AdministrationEDB
 
MongoDB - Aggregation Pipeline
MongoDB - Aggregation PipelineMongoDB - Aggregation Pipeline
MongoDB - Aggregation PipelineJason Terpko
 
Oracle_Multitenant_19c_-_All_About_Pluggable_D.pdf
Oracle_Multitenant_19c_-_All_About_Pluggable_D.pdfOracle_Multitenant_19c_-_All_About_Pluggable_D.pdf
Oracle_Multitenant_19c_-_All_About_Pluggable_D.pdfSrirakshaSrinivasan2
 
Introduction to MongoDB
Introduction to MongoDBIntroduction to MongoDB
Introduction to MongoDBRavi Teja
 
Postgresql Database Administration Basic - Day1
Postgresql  Database Administration Basic  - Day1Postgresql  Database Administration Basic  - Day1
Postgresql Database Administration Basic - Day1PoguttuezhiniVP
 
Bloat and Fragmentation in PostgreSQL
Bloat and Fragmentation in PostgreSQLBloat and Fragmentation in PostgreSQL
Bloat and Fragmentation in PostgreSQLMasahiko Sawada
 
OrientDB introduction - NoSQL
OrientDB introduction - NoSQLOrientDB introduction - NoSQL
OrientDB introduction - NoSQLLuca Garulli
 
Storing 16 Bytes at Scale
Storing 16 Bytes at ScaleStoring 16 Bytes at Scale
Storing 16 Bytes at ScaleFabian Reinartz
 
MySQL Ecosystem in 2023 - FOSSASIA'23 - Alkin.pptx.pdf
MySQL Ecosystem in 2023 - FOSSASIA'23 - Alkin.pptx.pdfMySQL Ecosystem in 2023 - FOSSASIA'23 - Alkin.pptx.pdf
MySQL Ecosystem in 2023 - FOSSASIA'23 - Alkin.pptx.pdfAlkin Tezuysal
 
EDB Postgres DBA Best Practices
EDB Postgres DBA Best PracticesEDB Postgres DBA Best Practices
EDB Postgres DBA Best PracticesEDB
 
Oracle sql high performance tuning
Oracle sql high performance tuningOracle sql high performance tuning
Oracle sql high performance tuningGuy Harrison
 
Tp Sql Server Integration Services 2008
Tp  Sql Server Integration Services  2008Tp  Sql Server Integration Services  2008
Tp Sql Server Integration Services 2008Abdelouahed Abdou
 
MySQL Cluster 8.0 tutorial
MySQL Cluster 8.0 tutorialMySQL Cluster 8.0 tutorial
MySQL Cluster 8.0 tutorialFrazer Clement
 

Was ist angesagt? (20)

Mastering PostgreSQL Administration
Mastering PostgreSQL AdministrationMastering PostgreSQL Administration
Mastering PostgreSQL Administration
 
MySQL Tuning
MySQL TuningMySQL Tuning
MySQL Tuning
 
Mongo DB
Mongo DBMongo DB
Mongo DB
 
MongoDB - Aggregation Pipeline
MongoDB - Aggregation PipelineMongoDB - Aggregation Pipeline
MongoDB - Aggregation Pipeline
 
MongoDB
MongoDBMongoDB
MongoDB
 
Oracle_Multitenant_19c_-_All_About_Pluggable_D.pdf
Oracle_Multitenant_19c_-_All_About_Pluggable_D.pdfOracle_Multitenant_19c_-_All_About_Pluggable_D.pdf
Oracle_Multitenant_19c_-_All_About_Pluggable_D.pdf
 
Introduction to MongoDB
Introduction to MongoDBIntroduction to MongoDB
Introduction to MongoDB
 
Postgresql Database Administration Basic - Day1
Postgresql  Database Administration Basic  - Day1Postgresql  Database Administration Basic  - Day1
Postgresql Database Administration Basic - Day1
 
MySql slides (ppt)
MySql slides (ppt)MySql slides (ppt)
MySql slides (ppt)
 
Bloat and Fragmentation in PostgreSQL
Bloat and Fragmentation in PostgreSQLBloat and Fragmentation in PostgreSQL
Bloat and Fragmentation in PostgreSQL
 
OrientDB introduction - NoSQL
OrientDB introduction - NoSQLOrientDB introduction - NoSQL
OrientDB introduction - NoSQL
 
Storing 16 Bytes at Scale
Storing 16 Bytes at ScaleStoring 16 Bytes at Scale
Storing 16 Bytes at Scale
 
MySQL Ecosystem in 2023 - FOSSASIA'23 - Alkin.pptx.pdf
MySQL Ecosystem in 2023 - FOSSASIA'23 - Alkin.pptx.pdfMySQL Ecosystem in 2023 - FOSSASIA'23 - Alkin.pptx.pdf
MySQL Ecosystem in 2023 - FOSSASIA'23 - Alkin.pptx.pdf
 
5 Steps to PostgreSQL Performance
5 Steps to PostgreSQL Performance5 Steps to PostgreSQL Performance
5 Steps to PostgreSQL Performance
 
An introduction to MongoDB
An introduction to MongoDBAn introduction to MongoDB
An introduction to MongoDB
 
EDB Postgres DBA Best Practices
EDB Postgres DBA Best PracticesEDB Postgres DBA Best Practices
EDB Postgres DBA Best Practices
 
Oracle sql high performance tuning
Oracle sql high performance tuningOracle sql high performance tuning
Oracle sql high performance tuning
 
PostgreSQL and RAM usage
PostgreSQL and RAM usagePostgreSQL and RAM usage
PostgreSQL and RAM usage
 
Tp Sql Server Integration Services 2008
Tp  Sql Server Integration Services  2008Tp  Sql Server Integration Services  2008
Tp Sql Server Integration Services 2008
 
MySQL Cluster 8.0 tutorial
MySQL Cluster 8.0 tutorialMySQL Cluster 8.0 tutorial
MySQL Cluster 8.0 tutorial
 

Ähnlich wie 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
 

Ähnlich wie 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...
 

Mehr von 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
 

Mehr von 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
 

Kürzlich hochgeladen

Potential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsPotential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsRavi Sanghani
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfpanagenda
 
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotesMuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotesManik S Magar
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Alkin Tezuysal
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersNicole Novielli
 
Connecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfConnecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfNeo4j
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxLoriGlavin3
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsNathaniel Shimoni
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxLoriGlavin3
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI AgeCprime
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality AssuranceInflectra
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesThousandEyes
 
Glenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security ObservabilityGlenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security Observabilityitnewsafrica
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesKari Kakkonen
 
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...Nikki Chapple
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity PlanDatabarracks
 
React Native vs Ionic - The Best Mobile App Framework
React Native vs Ionic - The Best Mobile App FrameworkReact Native vs Ionic - The Best Mobile App Framework
React Native vs Ionic - The Best Mobile App FrameworkPixlogix Infotech
 
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS:  6 Ways to Automate Your Data IntegrationBridging Between CAD & GIS:  6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integrationmarketing932765
 

Kürzlich hochgeladen (20)

Potential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsPotential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and Insights
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
 
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotesMuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
MuleSoft Online Meetup Group - B2B Crash Course: Release SparkNotes
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software Developers
 
Connecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfConnecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdf
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directions
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI Age
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
 
Glenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security ObservabilityGlenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security Observability
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examples
 
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity Plan
 
React Native vs Ionic - The Best Mobile App Framework
React Native vs Ionic - The Best Mobile App FrameworkReact Native vs Ionic - The Best Mobile App Framework
React Native vs Ionic - The Best Mobile App Framework
 
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS:  6 Ways to Automate Your Data IntegrationBridging Between CAD & GIS:  6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integration
 

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 }