Sub-Document API

The functions in this module can be used to specify operations to the lookup_in() and mutate_in() methods. Both the mutate_in and lookup_in methods can take multiple operations.

Any given operation is either valid in lookup_in() or mutate_in(); never both.

Internally every function in this module returns an object specifying the path, options, and value of the command, so for example:

cb.mutate_in(key,
             SD.upsert('path1', 'value1'),
             SD.insert('path2', 'value2', create_parents=True))

really becomes

cb.mutate_in(key,
             (CMD_SUBDOC_UPSERT, 'path1', 'value1', 0),
             (CMD_SUBDOC_INSERT, 'path2', 'value2', 1))

Thus, the actual operations are performed when the mutate_in or lookup_in methods are executed, the functions in this module just acting as an interface to specify what sorts of operations are to be executed.

Throughout the SDK documentation, this module is referred to as SD which is significantly easier to type than couchbase.subdocument. This is done via

import couchbase.subdocument as SD

Lookup Operations

couchbase.subdocument.get(path)[source]

Retrieve the value from the given path. The value is returned in the result. Valid only in lookup_in()

Parameters:path – The path to retrieve

See also

exists()

couchbase.subdocument.exists(path)[source]

Check if a given path exists. This is the same as get(), but the result will not contain the value. Valid only in lookup_in()

Parameters:path – The path to check

Mutation Operations

couchbase.subdocument.upsert(path, value, create_parents=False)[source]

Create or replace a dictionary path.

Parameters:
  • path – The path to modify
  • value – The new value for the path. This should be a native Python object which can be encoded into JSON (the SDK will do the encoding for you).
  • create_parents

    Whether intermediate parents should be created. This means creating any additional levels of hierarchy not already in the document, for example:

    {'foo': {}}
    

    Without create_parents, an operation such as

    cb.mutate_in("docid", SD.upsert("foo.bar.baz", "newValue"))
    

    would fail with couchbase.exceptions.SubdocPathNotFoundError because foo.bar does not exist. However when using the create_parents option, the server creates the new foo.bar dictionary and then inserts the baz value.

couchbase.subdocument.replace(path, value)[source]

Replace an existing path. This works on any valid path if the path already exists. Valid only in mutate_in()

Parameters:
  • path – The path to replace
  • value – The new value
couchbase.subdocument.insert(path, value, create_parents=False)[source]

Create a new path in the document. The final path element points to a dictionary key that should be created. Valid only in mutate_in()

Parameters:
  • path – The path to create
  • value – Value for the path
  • create_parents – Whether intermediate parents should be created
couchbase.subdocument.array_append(path, *values, **kwargs)[source]

Add new values to the end of an array.

Parameters:
  • path – Path to the array. The path should contain the array itself and not an element within the array
  • values – one or more values to append
  • create_parents – Create the array if it does not exist

Note

Specifying multiple values in values is more than just syntactical sugar. It allows the server to insert the values as one single unit. If you have multiple values to append to the same array, ensure they are specified as multiple arguments to array_append rather than multiple array_append commands to mutate_in()

This operation is only valid in mutate_in().

couchbase.subdocument.array_prepend(path, *values, **kwargs)[source]

Add new values to the beginning of an array.

Parameters:
  • path – Path to the array. The path should contain the array itself and not an element within the array
  • values – one or more values to append
  • create_parents – Create the array if it does not exist

This operation is only valid in mutate_in().

couchbase.subdocument.array_insert(path, *values)[source]

Insert items at a given position within an array.

Parameters:
  • path – The path indicating where the item should be placed. The path _should_ contain the desired position
  • values – Values to insert

This operation is only valid in mutate_in().

couchbase.subdocument.array_addunique(path, value, create_parents=False)[source]

Add a new value to an array if the value does not exist.

Parameters:
  • path – The path to the array
  • value – Value to add to the array if it does not exist. Currently the value is restricted to primitives: strings, numbers, booleans, and None values.
  • create_parents – Create the array if it does not exist

Note

The actual position of the new item is unspecified. This means it may be at the beginning, end, or middle of the existing array)

This operation is only valid in mutate_in().

couchbase.subdocument.remove(path)[source]

Remove an existing path in the document.

This operation is only valid in mutate_in().

Parameters:path – The path to remove
couchbase.subdocument.counter(path, delta, create_parents=False)[source]

Increment or decrement a counter in a document.

Parameters:
  • path – Path to the counter
  • delta – Amount by which to modify the value. The delta can be negative but not 0. It must be an integer (not a float) as well.
  • create_parents – Create the counter (and apply the modification) if it does not exist

Note

Unlike couchbase.bucket.Bucket.counter(), there is no initial argument. If the counter does not exist within the document (but its parent does, or create_parents is true), it will be initialized with the value of the delta.

This operation is only valid in mutate_in().

See also

upsert(), counter() (in Bucket)

Result Object

class couchbase.result.SubdocResult[source]

Class for objects returned via a subdoc operation. This may contain one or more values depending on the number of input commands.

The actual values from the result can be retrieved by iteration:

Iteration:

for value in rv:
    print(value)

Index:

value = rv['some.path']
value = rv[2]

Or by using the get() method:

error, value = rv.get('some.path')
error, value = rv.get(2)

Iterator and index access will raise exceptions when encountering a non-successful item. The get() usage will not throw an exception, however

access_ok

Dynamic property indicating if the document could be accessed (and thus results can be retrieved)

Returns:True if the document is accessible, False otherwise
command_count

Total number of input commands received.

For mutations (i.e. mutate_in()) this might be more than result_count.

exists(path_or_index)[source]

Checks if a path exists in the document. This is meant to be used for a corresponding exists() request.

Parameters:path_or_index – The path (or index) to check
Returns:True if the path exists, False if the path does not exist
Raise:An exception if the server-side check failed for a reason other than the path not existing.
get(path_or_index, default=None)[source]

Get details about a given result

Parameters:
  • path_or_index – The path (or index) of the result to fetch.
  • default – If the given result does not exist, return this value instead
Returns:

A tuple of (error, value). If the entry does not exist then (0, default) is returned.

result_count

Total number of results available. For mutations, this might be less than the command_count

Path Syntax

The path syntax is hierarchical and follows that of N1QL. Use a dot (.) to separate between components. A backtick may be used to escape dots or other special characters. Considering the dictionary:

{
    'dict': {
        'nestedDict': {
            'value': 123
        },
        'nestedArray': [1,2,3],
        'literal.dot': 'Hello',
        'literal[]brackets': 'World'
    },
    'array': [1,2,3],
    'primitive': True
}

Accessing paths can be done as:

  • dict
  • dict.nestedDict
  • dict.nestedDict.value
  • dict.nestedArray
  • dict.nestedArray[0]
  • dict.nestedArray[-1] (gets last element)
  • dict.`literal.dot`
  • dict.`literal[]brackets`
  • array
  • primitive