Key-Value (CRUD) operations

Key-Value (CRUD) operations

Key-Value or CRUD operations allow fast access to documents in Couchbase Server.

An overview of CRUD in Couchbase can be found at Accessing data.

Input values for document mutations

All Python objects which can be represented as JSON may be passed unmodified to a storage function, and be received via the get method without any additional modifications.

Storage operations accept a format keyword argument which may be one of FMT_JSON (to indicate the object should be serialized as JSON), FMT_UTF8 (to serialize the object as a UTF-8 encoded string), FMT_BYTES (to serialize an object as a raw set of bytes; note the Python object in question must be of type bytes), FMT_PICKLE (to serialize an object using Python's native pickle module). You may also define new formats and utilize them via a custom transcoder (see the API documentation for details).

Return value for CRUD operations

All Python SDK operations return a Result object (or a subclass thereof). The result object contains general operation information and item metadata retrieved from the server. Typically a subclass of Result will be returned which also contains operation-specific result information, such as the value field for a get() operation. The most common fields in a Result object are:

Name Description
value For retrieval-type operations, this field contains the value of the requested key.
rc Contains the raw error code received from libcouchbase. If this number is zero then the operation was successful; otherwise it will be an error. The CouchbaseError.rc_to_exctype() class method can be used to return the exception class which would have been thrown.
success This is a convenience property which is equivalent to rc == 0
cas An opaque object representing the resulting CAS value of the key that was operated on. This value is not meant to be user facing, but should be passed directly to other operations for locking purposes.

Note that for Twisted APIs, these objects are not returned per se, but rather a Deferred object is returned, and the appropriate Result or Failure object is passed into the callback or errback, respectively.

Creating and updating documents

Documents may be created and updated using the Bucket.upsert(), Bucket.insert(), and Bucket.replace() family of methods. Read more about the difference between these methods at Updating and creating documents in the Couchbase developer guide.
These methods accept two mandatory arguments:
  • key: The ID of the document to modify. This should be a Python string or unicode object.
  • value: The desired new value of the document. This may be anything that can be serialized as JSON (other input types can also be specified, see Input values for document mutations).
Additional options can be specified to the operation:
  • cas: The CAS value for the document. If the CAS on the server does not match the CAS supplied to the method, the operation will fail with a couchbase.exceptions.KeyExistsError error. See Concurrent Document Mutations for more information on the usage of CAS values.
  • ttl: Specify the expiry time for the document. If specified, the document will expire and no longer exist after the given number of seconds. See Document expiration for more information.
  • format: Specify the format of the new value. This indicates how the value should be serialized before being sent to the cluster. By default only JSON-serializable objects may be supplied as values. See Input values for document mutations.
  • persist_to, replicate_to: Specify durability requirements for the operations. A value of -1 indicates that the specific requirement will be set to the maximum possible.

Upon success, the returned Result object will contain the new CAS value of the document. If the document was not mutated successfully, an exception is raised. See Handling Exceptions for more information on exception types and how to handle them.

creating (Sync API)
rv = bucket.insert('document_name', {'some': 'value'})
print rv

Output:

OperationResult<RC=0x0, Key=u'document_name', CAS=0x707339a4125aaa13>
creating (Twisted API)
d_insert = bucket.insert('document_name', {'some': 'value'})

def on_ok(result):
    print "Result stored OK!", result

def on_err(err):
    print "Failed to insert!", err

d_insert.addCallbacks(on_ok, on_err)
Output:
Stored item OK OperationResult<RC=0x0, Key=u'document_name', CAS=0xb81d69a5125aaa13>
If the document being inserted already exists, the client will raise a couchbase.exceptions.KeyExistsError. If your application simply wants to set the value ignoring whether it exists or not, use the upsert() method.

Retrieving documents

Documents may be retrieved using the Bucket.get() method. The get() method has a single mandatory argument:
  • key: The document ID to retrieve
Other options include:
  • ttl: Set the expiration for the document. This operation is known as a get-and-touch operation. See Document expiration for more information.
  • replica: This may be passed as a boolean to issue a replica read. This may be used if access to the master/primary node is temporarily unavailable.
  • quiet: Suppress throwing exceptions if the document does not exist. Rather than throwing an exception, status can be obtained from the Result.success property.
    rv = bkt.get('maybe', quiet=True)
    if rv.success:
        handle_value(rv)
    else:
        print "Item not found"
Upon success, a ValueResult object is returned. The actual document may be access by using the ValueResult.value property. Additional properties may also be accessed from the returned object. See Return value for CRUD operations.

The ValueResult.value will contain a native Python object, deserialized from JSON (or another format, per Input values for document mutations).

If the document does not exist (and quiet=True was not specified), a couchbase.exceptions.NotFoundError will be raised.

Sync/gevent API
rv = bucket.get('document_name')
print "Result object is:", rv
print "Actual value is:", rv.value 

Sample output:

Result object is ValueResult<RC=0x0, Key=u'document_name', Value={u'some': u'value'}, 
   CAS=0x20504a5e6a5aaa13, Flags=0x2000000>
Actual value is {u'some': u'value'}
Twisted API
def on_ok(result):
    print "Got item. Result is", result
    print "Value is", result.value

def on_err(failure):
    print "Couldn't store!", failure

d_get = bkt.get('document_name')
d_get.addCallbacks(on_ok, on_err)

Sample output:

Got item. Result is ValueResult<RC=0x0, Key=u'document_name', Value={u'some': u'value'}, 
   CAS=0x20504a5e6a5aaa13, Flags=0x2000000>
Value is {u'some': u'value'}

If the item does not exist, the client will raise a couchbase.exceptions.NotFoundError, which you can catch:

Missing item; Sync API
from couchbase.exceptions import NotFoundError
try:
    rv = bkt.get('NOTEXISTENT')
except NotFoundError as e:
    print "Item not found", e
Missing item; Twisted API
def on_err(failure):
   failure.trap(NotFoundError)
   print "Item not found!"

Removing documents

Documents may be removed using the Bucket.remove() method. This method takes a single mandatory argument:
  • key: The ID of the document to remove
Some additional options:
  • quiet: Do not raise an exception when attempting to remove a document which does not exist.
  • cas: Only remove the document if the CAS has not changed.

Updating document expiration``

Document expiration can be performed using the Bucket.touch() method. See Document expiration for more information.

Counter document modification

A counter document may be modified using the Bucket.counter() method. See the linked section for more information on counter documents.

Raw append/prepend operations

Raw binary append and prepend operations can be performed using the Bucket.append() and Bucket.prepend() methods, respectively.

These functions behave similarly to the upsert() family of methods, except that the value argument should be the fragment to append or prepend (rather than the entire document). Additionally, the format argument must be supplied, and must be set to either couchbase.FMT_BYTES or couchbase.FMT_UTF8.