|
| 1 | +.. default-domain:: mongodb |
| 2 | +:title: MongoDB Use Cases - Session Objects |
| 3 | + |
| 4 | +.. http://www.mongodb.org/display/DOCS/Use+Case+-+Session+Objects |
| 5 | + |
| 6 | +=============== |
| 7 | +Session Objects |
| 8 | +=============== |
| 9 | + |
| 10 | + |
| 11 | +MongoDB is a good tool for storing HTTP session objects. |
| 12 | + |
| 13 | +One implementation model is to have a sessions collection, and store the |
| 14 | +session object's \_id value in a browser cookie. |
| 15 | + |
| 16 | +With its update-in-place design and general optimization to make updates |
| 17 | +fast, MongoDB is efficient at receiving an update to the session |
| 18 | +object on every single app server page view. |
| 19 | + |
| 20 | +Purging Old Sessions using TTL Collections |
| 21 | +------------------------------------------ |
| 22 | + |
| 23 | +The best method to manage and purge old sessions is to use a |
| 24 | +:term:`TTL Collection <mongodb:ttl-collections>`. |
| 25 | +A TTL collection is a MongoDB collection which has an ``expireAfterSeconds`` |
| 26 | +index on an :term:`ISODate <mongodb:isodate>` field. |
| 27 | + |
| 28 | +For example, create a collection :samp:`sessions` with three fields: |
| 29 | + |
| 30 | + :samp:`_id` |
| 31 | + |
| 32 | + Automatically created by MongoDB |
| 33 | + |
| 34 | + :samp:`lastUsed` |
| 35 | + |
| 36 | + An ISODate field which you will update every time an action occurs |
| 37 | + in the session. |
| 38 | + |
| 39 | + :samp:`sessionId` |
| 40 | + |
| 41 | + An identifier for the session. This could be an ObjectId from |
| 42 | + another collection for example. |
| 43 | + |
| 44 | +.. code-block:: javascript |
| 45 | + |
| 46 | + > db.createCollection('sessions'); |
| 47 | + {"ok": 1} |
| 48 | + |
| 49 | + > var record = { lastUsed: ISODate(), sessionId: "1cf41e17e21d5697ac7ed84d10caa456"} |
| 50 | + > db.sessions.insert(record) |
| 51 | + > db.sessions.find().pretty() |
| 52 | + { |
| 53 | + "_id" : ObjectId("50fee58e95fa0c941f134114"), |
| 54 | + "lastUsed" : ISODate("2013-01-22T19:16:23.570Z"), |
| 55 | + "sessionId" : "1cf41e17e21d5697ac7ed84d10caa456" |
| 56 | + } |
| 57 | + |
| 58 | +You now have a collection with one record. Now create the TTL index on the |
| 59 | +collection: |
| 60 | + |
| 61 | +.. code-block:: javascript |
| 62 | + |
| 63 | + > db.sessions.ensureIndex({lastUsed:1}, {expireAfterSeconds:300}) |
| 64 | + |
| 65 | +This creates a TTL index on the :samp:`lastUsed` field. |
| 66 | +Any document whose :samp:`lastUsed` field has a time older than five |
| 67 | +minutes (300 seconds) will be purged. |
| 68 | + |
| 69 | +.. code-block:: javascript |
| 70 | + |
| 71 | + > db.sessions.getIndexes() |
| 72 | + [ |
| 73 | + { |
| 74 | + "v" : 1, |
| 75 | + "key" : { |
| 76 | + "_id" : 1 |
| 77 | + }, |
| 78 | + "ns" : "writing.sessions", |
| 79 | + "name" : "_id_" |
| 80 | + }, |
| 81 | + { |
| 82 | + "v" : 1, |
| 83 | + "key" : { |
| 84 | + "lastUsed" : 1 |
| 85 | + }, |
| 86 | + "ns" : "writing.sessions", |
| 87 | + "name" : "lastUsed_1", |
| 88 | + "expireAfterSeconds" : 300 |
| 89 | + } |
| 90 | + ] |
| 91 | + |
| 92 | +And if we wait a few minutes that solitary document will be purged: |
| 93 | + |
| 94 | +.. code-block:: javascript |
| 95 | + |
| 96 | + > db.sessions.find() |
| 97 | + > |
| 98 | + |
| 99 | +.. note:: |
| 100 | + |
| 101 | + If you insert a document whose timestamp is already ``older`` than |
| 102 | + the expiration window set in :samp:`expireAfterSeconds`, MongoDB |
| 103 | + will insert the document and then purge it at the next run of the |
| 104 | + TTL scavenger process. |
| 105 | + |
| 106 | + |
| 107 | +Aging Out Old Sessions using Capped Collections |
| 108 | +----------------------------------------------- |
| 109 | + |
| 110 | +One method to age out old sessions is to use the auto-LRU facility of |
| 111 | +:term:`capped collections <mongodb:capped collections>`. |
| 112 | +A complication is that objects in capped collections may not grow beyond |
| 113 | +their initial allocation size. |
| 114 | +To handle this, we can "pre-pad" the objects to some maximum size on |
| 115 | +initial addition, and then on further updates we are fine if we do not |
| 116 | +go above the limit. The following MongoDB shell JavaScript example |
| 117 | +demonstrates padding: |
| 118 | + |
| 119 | +.. code-block:: javascript |
| 120 | + |
| 121 | + > db.createCollection('sessions', { capped: true, size : 1000000 } ) |
| 122 | + {"ok" : 1} |
| 123 | + > p = ""; |
| 124 | + > for( x = 0; x < 100; x++ ) p += 'x'; |
| 125 | + > s1 = { info: 'example', _padding : p }; |
| 126 | + {"info" : "example" , "_padding" : "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"} |
| 127 | + > db.sessions.save(s1) |
| 128 | + > s1 |
| 129 | + {"info" : "example" , "_padding" : "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" , "_id" : ObjectId( "4aafb74a5761d147677233b0") } |
| 130 | + |
| 131 | + > // when updating later |
| 132 | + > s1 = db.sessions.find( { _id : ObjectId( "4aafb74a5761d147677233b0") } ) |
| 133 | + {"_id" : ObjectId( "4aafb74a5761d147677233b0") , "info" : "example" , "_padding" : "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"} |
| 134 | + > delete s._padding; |
| 135 | + true |
| 136 | + > s.x = 3; // add a new field |
| 137 | + 3 |
| 138 | + > db.sessions.save(s); |
| 139 | + > s |
| 140 | + {"_id" : ObjectId( "4aafb5a25761d147677233af") , "info" : "example" , "x" : 3} |
0 commit comments