IBM Cloudant Python client library providing comprehensive interface for Cloudant and CouchDB databases
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Query documents using Cloudant Query (Mango) with comprehensive indexing support including JSON indexes, text search, and special indexes with pagination and partitioning capabilities.
Execute queries using Cloudant Query (Mango) syntax.
class Query:
"""
Cloudant query interface using Mango query language.
"""
def __init__(self, database, selector=None, fields=None, **kwargs):
"""
Initialize query builder.
Parameters:
- database (CloudantDatabase): Target database
- selector (dict): Query selector (WHERE clause)
- fields (list[str]): Fields to return (SELECT clause)
- sort (list[dict]): Sort specification
- limit (int): Maximum results
- skip (int): Number of results to skip
- bookmark (str): Pagination bookmark
- use_index (str | list): Index to use for query
- execution_stats (bool): Include execution statistics
"""
def __call__(self, **kwargs):
"""
Execute query with optional parameter overrides.
Parameters:
- **kwargs: Query parameters to override
Returns:
QueryResult: Query result iterator with bookmark support
"""
def custom_result(self, **options):
"""
Execute query with custom result options.
Parameters:
- **options: Result collection options
Returns:
QueryResult: Custom result iterator
"""
@property
def result(self):
"""Default query result collection"""Direct query execution methods on database instances.
class CouchDatabase(dict):
"""Database query methods."""
def get_query_result(self, selector, fields=None, raw_result=False, **kwargs):
"""
Execute Cloudant Query and return results.
Parameters:
- selector (dict): Query selector using MongoDB-style syntax
- fields (list[str]): Fields to return in results
- raw_result (bool): Return raw response without processing
- sort (list[dict]): Sort specification [{"field": "asc|desc"}]
- limit (int): Maximum number of results
- skip (int): Number of results to skip
- bookmark (str): Pagination bookmark from previous query
- use_index (str | list): Force use of specific index
- execution_stats (bool): Include query execution statistics
Returns:
QueryResult | dict: Query results or raw response
Raises:
CloudantDatabaseException: Query execution failed
"""
def get_partitioned_query_result(self, partition_key, selector, fields=None, raw_result=False, **kwargs):
"""
Execute query within a specific partition.
Parameters:
- partition_key (str): Partition identifier
- selector (dict): Query selector
- fields (list[str]): Fields to return
- raw_result (bool): Return raw response
- **kwargs: Same options as get_query_result()
Returns:
QueryResult | dict: Partitioned query results
"""Create and manage indexes for query optimization.
class CouchDatabase(dict):
"""Index management methods."""
def get_query_indexes(self, raw_result=False):
"""
List all query indexes in the database.
Parameters:
- raw_result (bool): Return raw response
Returns:
list[dict] | dict: Index definitions or raw response
"""
def create_query_index(self, design_document_id=None, index_name=None, index_type='json', partitioned=None, **kwargs):
"""
Create a query index.
Parameters:
- design_document_id (str): Design document ID for index
- index_name (str): Name for the index
- index_type (str): Index type ('json', 'text', 'special')
- partitioned (bool): Whether index is partitioned
- fields (list[str | dict]): Fields to index
- selector (dict): Partial filter selector for index
Returns:
dict: Index creation response
Raises:
CloudantIndexException: Index creation failed
"""
def delete_query_index(self, design_document_id, index_type, index_name):
"""
Delete a query index.
Parameters:
- design_document_id (str): Design document containing index
- index_type (str): Type of index to delete
- index_name (str): Name of index to delete
Returns:
dict: Deletion response
Raises:
CloudantIndexException: Index deletion failed
"""Object-oriented index management.
class Index:
"""
JSON query index management.
"""
def __init__(self, database, design_document_id=None, name=None, partitioned=None, **kwargs):
"""
Initialize index instance.
Parameters:
- database (CloudantDatabase): Target database
- design_document_id (str): Design document ID
- name (str): Index name
- partitioned (bool): Partitioned index flag
- fields (list[str | dict]): Fields to index
- selector (dict): Partial filter selector
"""
def create(self):
"""
Create index in database.
Returns:
dict: Creation response
Raises:
CloudantIndexException: Creation failed
"""
def delete(self):
"""
Delete index from database.
Returns:
dict: Deletion response
Raises:
CloudantIndexException: Deletion failed
"""
@property
def index_url(self):
"""Index URL endpoint"""
@property
def design_document_id(self):
"""Design document ID containing index"""
@property
def name(self):
"""Index name"""
@property
def type(self):
"""Index type ('json', 'text', 'special')"""
class TextIndex(Index):
"""
Text search index for full-text search capabilities.
"""
class SpecialIndex(Index):
"""
Special index for built-in indexes like _all_docs.
"""Sliceable, key-accessible, and iterable result collections for efficient data access and pagination.
class Result:
"""
Key accessible, sliceable, and iterable interface to result collections.
Supports efficient paged iteration and flexible data access patterns
including index-based access, key-based access, and slicing.
"""
def __init__(self, method_ref, **options):
"""
Initialize result collection.
Parameters:
- method_ref: Callable that returns JSON result data
- descending (bool): Return documents in descending key order
- endkey: Stop returning records at specified key
- endkey_docid (str): Stop at specified document ID
- group (bool): Group reduce results
- group_level (int): Group level for complex keys
- include_docs (bool): Include full document content
- inclusive_end (bool): Include rows with endkey
- key: Return only documents matching specified key
- keys (list): Return only documents matching specified keys
- limit (int): Maximum number of results
- page_size (int): Page size for iteration (default: 100)
- reduce (bool): Use reduce function
- skip (int): Skip specified number of rows
- stable (bool): Use stable set of shards
- stale (str): Allow stale results ('ok' or 'update_after')
- startkey: Start returning records from specified key
- startkey_docid (str): Start from specified document ID
- update (str): Update view before/after response ('true', 'false', 'lazy')
"""
def __getitem__(self, arg):
"""
Key access and slicing support.
Parameters:
- arg (int): Index access - skip N records, get next
- arg (str | list | ResultByKey): Key access - get records matching key
- arg (slice): Slice access - get range of records
Returns:
list: Rows data in JSON format
"""
def __iter__(self):
"""
Iterate over result collection with automatic pagination.
Yields:
dict: Individual result documents
"""
def all(self):
"""
Retrieve all results as a list.
Returns:
list: All result documents
"""
class ResultByKey:
"""
Wrapper for values used to retrieve records by document key.
Distinguishes between index access and key access when key is numeric.
"""
def __init__(self, value):
"""
Initialize key wrapper.
Parameters:
- value: The key value to match against
"""
def __call__(self):
"""
Get the wrapped key value.
Returns:
The original key value
"""
class QueryResult(Result):
"""
Specialized result collection for Cloudant Query results.
Extends Result with query-specific iteration using bookmarks
and index-only access patterns.
"""
def __init__(self, query, **options):
"""
Initialize query result collection.
Parameters:
- query: Query callable reference
- bookmark (str): Pagination bookmark
- fields (list[str]): Fields to return
- page_size (int): Page size for iteration (default: 100)
- r (int): Read quorum for results
- selector (dict): Query selector criteria
- sort (list): Sort specification
- use_index (str): Specific index to use
"""
def __getitem__(self, arg):
"""
Index-only access and slicing for query results.
Parameters:
- arg (int): Index access only
- arg (slice): Index slice only (no key-based slicing)
Returns:
list: Document data in JSON format
Raises:
ResultException: If key-based access attempted
"""Full-text search using Lucene indexes.
class CloudantDatabase(CouchDatabase):
"""Search methods."""
def get_search_result(self, ddoc_id, index_name, **query_params):
"""
Execute full-text search query.
Parameters:
- ddoc_id (str): Design document ID containing search index
- index_name (str): Search index name
- q (str): Lucene query string
- bookmark (str): Pagination bookmark
- limit (int): Maximum results
- sort (str | list): Sort specification
- include_docs (bool): Include document content
- include_fields (list[str]): Specific fields to include
- ranges (dict): Numeric range facets
- counts (list[str]): String facet counts
- drilldown (list[list]): Facet drill-down
- group_field (str): Group results by field
- group_limit (int): Results per group
- group_sort (str | list): Sort within groups
Returns:
dict: Search results with hits, facets, and metadata
Raises:
CloudantDatabaseException: Search failed
"""
def get_partitioned_search_result(self, partition_key, ddoc_id, index_name, **query_params):
"""
Execute search within specific partition.
Parameters:
- partition_key (str): Partition identifier
- ddoc_id (str): Design document ID
- index_name (str): Search index name
- **query_params: Same options as get_search_result()
Returns:
dict: Partitioned search results
"""from cloudant import cloudant
with cloudant('user', 'pass', account='myaccount') as client:
db = client['my_database']
# Simple equality query
selector = {'type': 'user', 'status': 'active'}
result = db.get_query_result(selector)
for doc in result:
print(f"Active user: {doc['name']}")
# Query with specific fields
fields = ['_id', 'name', 'email']
result = db.get_query_result(selector, fields=fields)
for doc in result:
print(f"User: {doc['name']} ({doc['email']})")from cloudant import cloudant
with cloudant('user', 'pass', account='myaccount') as client:
db = client['my_database']
# Range and comparison operators
selector = {
'type': 'order',
'total': {'$gt': 100, '$lt': 1000},
'status': {'$in': ['pending', 'processing']},
'created_date': {'$gte': '2023-01-01'}
}
# Sort by total descending, then by date ascending
sort = [{'total': 'desc'}, {'created_date': 'asc'}]
result = db.get_query_result(
selector=selector,
sort=sort,
limit=50,
fields=['_id', 'total', 'status', 'created_date']
)
for doc in result:
print(f"Order {doc['_id']}: ${doc['total']} - {doc['status']}")
# Text search with regex
selector = {
'name': {'$regex': '(?i)john.*'}, # Case-insensitive regex
'tags': {'$all': ['developer', 'python']}
}
result = db.get_query_result(selector)from cloudant import cloudant
from cloudant.query import Query
with cloudant('user', 'pass', account='myaccount') as client:
db = client['my_database']
# Create reusable query
user_query = Query(
db,
selector={'type': 'user'},
fields=['_id', 'name', 'email', 'created_date'],
sort=[{'created_date': 'desc'}]
)
# Execute with default parameters
recent_users = user_query()
for user in recent_users:
print(f"User: {user['name']}")
# Execute with parameter overrides
active_users = user_query(
selector={'type': 'user', 'status': 'active'},
limit=10
)
for user in active_users:
print(f"Active user: {user['name']}")from cloudant import cloudant
from cloudant.index import Index, TextIndex
with cloudant('user', 'pass', account='myaccount') as client:
db = client['my_database']
# List existing indexes
indexes = db.get_query_indexes()
for idx in indexes['indexes']:
print(f"Index: {idx['name']} on {idx['def']['fields']}")
# Create JSON index
db.create_query_index(
fields=['type', 'status', 'created_date'],
index_name='type_status_date_idx'
)
# Create partial index with selector
db.create_query_index(
fields=['email'],
index_name='user_email_idx',
selector={'type': 'user'} # Only index user documents
)
# Using Index class
user_index = Index(
db,
name='user_search_idx',
fields=['name', 'email', {'created_date': 'desc'}]
)
user_index.create()
# Create text search index
search_index = TextIndex(
db,
name='content_search',
fields=[
{'name': 'title', 'type': 'string'},
{'name': 'content', 'type': 'string'},
{'name': 'tags', 'type': 'string'}
]
)
search_index.create()
# Delete index
db.delete_query_index('_design/user_search_idx', 'json', 'user_search_idx')from cloudant import cloudant
with cloudant('user', 'pass', account='myaccount') as client:
db = client['my_database']
selector = {'type': 'product'}
limit = 25
bookmark = None
page = 1
while True:
result = db.get_query_result(
selector=selector,
limit=limit,
bookmark=bookmark,
sort=[{'name': 'asc'}]
)
docs = list(result)
if not docs:
break
print(f"Page {page}: {len(docs)} products")
for doc in docs:
print(f" - {doc['name']}")
# Get bookmark for next page
if hasattr(result, 'bookmark'):
bookmark = result.bookmark
if not bookmark: # No more pages
break
else:
break
page += 1from cloudant import cloudant
with cloudant('user', 'pass', account='myaccount') as client:
db = client['my_database']
# Simple text search
search_result = db.get_search_result(
'content_ddoc',
'content_search',
q='python AND database',
limit=20,
include_docs=True
)
print(f"Found {search_result['total_rows']} matches")
for hit in search_result['rows']:
doc = hit['doc']
print(f"Match: {doc['title']} (score: {hit['order'][0]})")
# Advanced search with facets
search_result = db.get_search_result(
'content_ddoc',
'content_search',
q='*:*', # Match all documents
counts=['category', 'author'], # Facet counts
ranges={'price': {'low': '[0 TO 50]', 'high': '[50 TO *]'}},
drilldown=[['category', 'electronics']], # Filter by category
group_field='author',
group_limit=3
)
# Display facets
for facet_name, counts in search_result.get('counts', {}).items():
print(f"{facet_name} facets:")
for value, count in counts.items():
print(f" {value}: {count}")from cloudant import cloudant
with cloudant('user', 'pass', account='myaccount') as client:
# Use partitioned database
db = client['partitioned_database']
# Query within specific partition
result = db.get_partitioned_query_result(
'user123',
selector={'type': 'activity'},
sort=[{'timestamp': 'desc'}],
limit=10
)
for activity in result:
print(f"Activity: {activity['action']} at {activity['timestamp']}")
# Search within partition
search_result = db.get_partitioned_search_result(
'user123',
'activity_ddoc',
'activity_search',
q='login OR logout',
include_docs=True
)from cloudant import cloudant
from cloudant.result import Result, ResultByKey
with cloudant('user', 'pass', account='myaccount') as client:
db = client['my_database']
# Create result collection from view
result = Result(db.all_docs, include_docs=True)
# Index-based access
first_doc = result[0] # Skip 0, get 1st document
tenth_doc = result[9] # Skip 9, get 10th document
# Key-based access
specific_doc = result['doc_key_123'] # Get documents with key 'doc_key_123'
numeric_key = result[ResultByKey(42)] # Get documents with numeric key 42
# Slicing
first_ten = result[0:10] # First 10 documents
next_batch = result[10:20] # Documents 11-20
all_after_100 = result[100:] # All documents after 100th
key_range = result['aaa':'zzz'] # Documents with keys between 'aaa' and 'zzz'
# Iteration with automatic pagination
for doc in result:
print(f"Document: {doc['_id']}")
if doc.get('_id') == 'stop_here':
break
# Get all results at once
all_docs = result.all()
print(f"Total documents: {len(all_docs)}")
# Custom page size for iteration
large_result = Result(db.all_docs, page_size=1000, include_docs=True)
for doc in large_result:
process_document(doc)from cloudant import cloudant
from cloudant.query import Query
from cloudant.result import QueryResult
with cloudant('user', 'pass', account='myaccount') as client:
db = client['my_database']
# Create query result collection
query = Query(db, selector={'type': 'user'})
query_result = QueryResult(query, page_size=50)
# Index-based access only (no key-based access for queries)
first_user = query_result[0]
users_10_to_20 = query_result[10:20]
# Iteration with bookmark pagination
for user in query_result:
print(f"User: {user['name']}")
# Custom query result with sort
sorted_result = QueryResult(
query,
sort=[{'created_date': 'desc'}],
fields=['_id', 'name', 'email']
)
recent_users = sorted_result[0:10] # 10 most recent usersfrom cloudant import cloudant
from cloudant.result import Result, ResultByKey
with cloudant('user', 'pass', account='myaccount') as client:
db = client['my_database']
# Complex key access (for views with complex keys)
view_result = Result(db['_design/stats']['by_date_and_type'])
# Access by complex key
today_users = view_result[['2023-12-01', 'user']]
date_range = view_result[['2023-12-01']:['2023-12-31']]
# Numeric key handling
numeric_result = Result(db['_design/counters']['by_id'])
doc_by_id = numeric_result[ResultByKey(12345)] # Key access, not index
twelfth_doc = numeric_result[11] # Index access (12th document)
# Conditional iteration
filtered_result = Result(
db.all_docs,
startkey='prefix_',
endkey='prefix_\ufff0', # All keys starting with 'prefix_'
include_docs=True
)
for doc in filtered_result:
if doc['doc']['status'] == 'active':
print(f"Active document: {doc['id']}")
# Reduce view results
stats_result = Result(
db['_design/analytics']['monthly_stats'],
group=True,
group_level=2
)
for stat in stats_result:
month = stat['key']
value = stat['value']
print(f"Month {month}: {value} events")from cloudant import cloudant
with cloudant('user', 'pass', account='myaccount') as client:
db = client['my_database']
# Force use of specific index
result = db.get_query_result(
selector={'type': 'user', 'status': 'active'},
use_index='user_status_idx',
execution_stats=True
)
# Check execution statistics
if hasattr(result, 'execution_stats'):
stats = result.execution_stats
print(f"Execution time: {stats.get('execution_time_ms')}ms")
print(f"Results examined: {stats.get('results_returned')}")
print(f"Documents examined: {stats.get('total_docs_examined')}")
print(f"Index used: {stats.get('index', {}).get('name')}")
# Query with hint for index selection
result = db.get_query_result(
selector={'category': 'electronics', 'price': {'$lt': 500}},
use_index=['category', 'price'], # Compound index
sort=[{'price': 'asc'}]
)Query and indexing operations can raise specific exceptions:
from cloudant import cloudant
from cloudant.error import CloudantDatabaseException, CloudantIndexException
with cloudant('user', 'pass', account='myaccount') as client:
db = client['my_database']
try:
# Query with invalid selector
result = db.get_query_result({'invalid_operator': {'$invalid': 'value'}})
except CloudantDatabaseException as e:
print(f"Query failed: {e}")
try:
# Create duplicate index
db.create_query_index(fields=['email'], index_name='existing_index')
except CloudantIndexException as e:
print(f"Index creation failed: {e}")
try:
# Delete non-existent index
db.delete_query_index('_design/missing', 'json', 'missing_index')
except CloudantIndexException as e:
print(f"Index deletion failed: {e}")Install with Tessl CLI
npx tessl i tessl/pypi-cloudant