Search:

Search all manuals
Search this manual
Manual
Couchbase Server Manual 2.0
Community Wiki and Resources
Download Couchbase Server 2.0
Couchbase Developer Guide 2.0
Client Libraries
Couchbase Server Forum
Additional Resources
Community Wiki
Community Forums
Couchbase SDKs
Parent Section
9.9 View and Query Pattern Samples
Chapter Sections
Chapters

9.9.11. Simulating Transactions

Couchbase Server does not support transactions, but the effect can be simulated by writing a suitable document and view definition that produces the effect while still only requiring a single document update to be applied.

For example, consider a typical banking application, the document structure could be as follows:

JSON
{
   "account" : "James",
   "value" : 100
}

A corresponding record for another account:

JSON
{
   "account" : "Alice",
   "value" : 200
}

To get the balance of each account, the following map():

Javascript
function(doc, meta) {
    if (doc.account && doc.value)
    {
      emit(doc.account,doc.value);
    }
}

The reduce() function can use the built-in _sum function.

When queried, using a group_level of 1, the balance of the accounts is displayed:

JSON
{"rows":[
{"key":"Alice","value":200},
{"key":"James","value":100}
]
}

Money in an account can be updated just by adding another record into the system with the account name and value. For example, adding the record:

JSON
{
   "account" : "James",
   "value" : 50
}

Re-querying the view produces an updated balance for each account:

JSON
{"rows":[
{"key":"Alice","value":200},
{"key":"James","value":150}
]
}

However, if Alice wants to transfer $100 to James, two record updates are required:

  1. A record that records an update to Alice's account to reduce the value by 100.

  2. A record that records an update to James's account to increase the value by 100.

Unfortunately, the integrity of the transaction could be compromised in the event of a problem between step 1 and step 2. Alice's account may be deducted, without updates James' record.

To simulate this operation while creating (or updating) only one record, a combination of a transaction record and a view must be used. The transaction record looks like this:

JSON
{
     "fromacct" : "Alice",
     "toacct" : "James",
     "value" : 100
}

The above records the movement of money from one account to another. The view can now be updated to handle a transaction record and output a row through emit() to update the value for each account.

Javascript
function(doc, meta) 
{
  if (doc.fromacct)
  {
    emit(doc.fromacct, -doc.value);
    emit(doc.toacct, doc.value);
  } 
  else
  {
    emit(doc.account, doc.value);
  }
}

The above map() effectively generates two fake rows, one row subtracts the amount from the source account, and adds the amount to the destination account. The resulting view then uses the reduce() function to sum up the transaction records for each account to arrive at a final balance:

JSON
{"rows":[
{"key":"Alice","value":100},
{"key":"James","value":250}
]
}

Throughout the process, only one record has been created, and therefore transient problems with that record update can be captured without corrupting or upsetting the existing stored data.