Updating documents

Update documents by adding or replacing its content.

Documents can be modified in numerous ways. Here are the things you can do with libcouchbase:
  • Add a new document
  • Replace an existing document
  • Add a new document (or replacing its value if it already exists)
  • Append data to the end of a document
  • Prepend data to the beginning of a document
All these modifications can be done in the same manner as described in Retrieving documents. How a document is modified is dependent on what was specified in the operation field:
  • LCB_ADD only creates the document if it does not already exist. It fails if the document is already present.
  • LCB_REPLACE only replaces the document if it already exists. It fails unless the document is already present.
  • LCB_SET unconditionally stores the document to the cluster, regardless of whether it already exists or not.

Conditional Updates based on State

You can choose to only update a document conditionally based on it being in some known state.

Modifying a document based on its state helps resolve race conditions where two concurrent threads of control attempt to modify the same document. This feature, known as compare and swap (CAS), allows you to specify an opaque 64-bit identifier representing the current state of the document to the server. If the CAS identifier at the server matches the one specified in the request then the operation is performed successfully. Otherwise, it indicates that another modification has been performed on the document. The CAS of the document is modified during each modification to the document.

An example use case of CAS is when adding to a list of items. Assume the following states:
Key: numbers Value: "[ 1, 2, 3 ]"
CAS=0
Now assume your application adds numbers to this list:
to_add = rand();
item = parse_json(get("numbers"));
item += to_add store("numbers", item);
If both applications run this piece of code at the same time, there’s a good chance one of the modifications will be lost, because the document might have changed between the original get() and the subsequent store(). Consider:
  1. App1 gets the numbers key with a value of "[1, 2, 3 ]". The item’s CAS is now 100, and this is the CAS that App1 has.
  2. App2 sets the numbers key with a value of "[1, 2, 3, 99]". The item’s CAS is now 200
  3. App1 sets the numbers key with a value of "[1, 2, 3, 76]".
If each application instance used the cas field to specify the CAS of the document known to it, this scenario would be averted because App1 would pass 100 as the CAS value, and the server would reject the modification because the CAS has since changed (via App2) to 200. To use the CAS in libcouchbase, set the cas field in the operation structure.
cmd.v.v0.cas = cas_value;
The CAS itself can be obtained in the response structure within the callbacks for storage and retrieval operations:
cas_value = resp->v.v0.cas;