or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

authentication.mdchange-feeds.mddatabase-management.mddocument-operations.mderror-handling.mdhttp-adapters.mdindex.mdquery-indexing.mdreplication.mdscheduler-monitoring.mdsecurity-document.mdviews-design-documents.md

document-operations.mddocs/

0

# Document Operations

1

2

Complete CRUD operations for JSON documents with attachment support, conflict resolution, batch operations, and field-level update utilities.

3

4

## Capabilities

5

6

### Document Access

7

8

Access documents through dict-like interface on the database.

9

10

```python { .api }

11

class CouchDatabase(dict):

12

"""Dict-like interface for document access."""

13

14

def keys(self, remote=False):

15

"""

16

Get all document IDs in the database.

17

18

Parameters:

19

- remote (bool): Fetch from server (default: False, uses cache)

20

21

Returns:

22

list[str]: Document IDs

23

"""

24

25

def __getitem__(self, key):

26

"""

27

Access document by ID.

28

29

Parameters:

30

- key (str): Document ID

31

32

Returns:

33

Document: Document instance

34

"""

35

36

def get(self, key, remote=False):

37

"""

38

Safe document access.

39

40

Parameters:

41

- key (str): Document ID

42

- remote (bool): Fetch from server if not cached

43

44

Returns:

45

Document | None: Document instance or None if not found

46

"""

47

48

def __contains__(self, key):

49

"""

50

Check if document exists.

51

52

Parameters:

53

- key (str): Document ID

54

55

Returns:

56

bool: True if document exists

57

"""

58

59

def __iter__(self, remote=True):

60

"""

61

Iterate over all documents.

62

63

Parameters:

64

- remote (bool): Fetch from server (default: True)

65

66

Yields:

67

Document: Document instances

68

"""

69

```

70

71

### Document Creation

72

73

Create new documents in the database.

74

75

```python { .api }

76

class CouchDatabase(dict):

77

"""Document creation methods."""

78

79

def create_document(self, data, throw_on_exists=False):

80

"""

81

Create document with provided data.

82

83

Parameters:

84

- data (dict): Document data including optional _id

85

- throw_on_exists (bool): Raise exception if document exists

86

87

Returns:

88

Document: Created document instance

89

90

Raises:

91

CloudantDocumentException: Document creation failed

92

"""

93

94

def new_document(self):

95

"""

96

Create empty document with generated ID.

97

98

Returns:

99

Document: Empty document with auto-generated _id

100

"""

101

```

102

103

### Document Class

104

105

Core document operations with CRUD functionality.

106

107

```python { .api }

108

class Document(dict):

109

"""

110

Represents a CouchDB/Cloudant document with CRUD operations.

111

"""

112

113

def __init__(self, database, document_id=None, **kwargs):

114

"""

115

Initialize document instance.

116

117

Parameters:

118

- database (CouchDatabase | CloudantDatabase): Parent database

119

- document_id (str): Document ID (auto-generated if None)

120

- **kwargs: Initial document fields

121

"""

122

123

def exists(self):

124

"""

125

Check if document exists in database.

126

127

Returns:

128

bool: True if document exists on server

129

"""

130

131

def create(self):

132

"""

133

Create document in database.

134

135

Returns:

136

dict: Creation response with _id and _rev

137

138

Raises:

139

CloudantDocumentException: Document already exists or creation failed

140

"""

141

142

def fetch(self):

143

"""

144

Fetch latest document version from database.

145

146

Returns:

147

None: Document data is updated in-place

148

149

Raises:

150

CloudantDocumentException: Document not found or fetch failed

151

"""

152

153

def save(self):

154

"""

155

Save document changes to database.

156

157

Returns:

158

dict: Save response with updated _rev

159

160

Raises:

161

CloudantDocumentException: Conflict or save failed

162

"""

163

164

def delete(self):

165

"""

166

Delete document from database.

167

168

Returns:

169

dict: Deletion response

170

171

Raises:

172

CloudantDocumentException: Deletion failed

173

"""

174

175

def json(self):

176

"""

177

Get JSON representation of document.

178

179

Returns:

180

str: JSON string of document data

181

"""

182

183

@property

184

def document_url(self):

185

"""Document URL endpoint"""

186

187

@property

188

def r_session(self):

189

"""HTTP request session"""

190

```

191

192

### Field Operations

193

194

Utilities for updating document fields with conflict resolution.

195

196

```python { .api }

197

class Document(dict):

198

"""Field update operations."""

199

200

def update_field(self, action, field, value, max_tries=10):

201

"""

202

Update document field with conflict resolution.

203

204

Parameters:

205

- action (callable): Update function (list_field_append, list_field_remove, field_set)

206

- field (str): Field name to update

207

- value: Value for the update operation

208

- max_tries (int): Maximum retry attempts for conflicts

209

210

Returns:

211

dict: Update response

212

213

Raises:

214

CloudantDocumentException: Update failed after max retries

215

"""

216

217

@staticmethod

218

def list_field_append(doc, field, value):

219

"""

220

Helper to append value to list field.

221

222

Parameters:

223

- doc (dict): Document data

224

- field (str): Field name

225

- value: Value to append

226

227

Returns:

228

dict: Updated document

229

"""

230

231

@staticmethod

232

def list_field_remove(doc, field, value):

233

"""

234

Helper to remove value from list field.

235

236

Parameters:

237

- doc (dict): Document data

238

- field (str): Field name

239

- value: Value to remove

240

241

Returns:

242

dict: Updated document

243

"""

244

245

@staticmethod

246

def field_set(doc, field, value):

247

"""

248

Helper to set field value.

249

250

Parameters:

251

- doc (dict): Document data

252

- field (str): Field name

253

- value: Value to set

254

255

Returns:

256

dict: Updated document

257

"""

258

```

259

260

### Attachment Operations

261

262

Manage binary attachments on documents.

263

264

```python { .api }

265

class Document(dict):

266

"""Attachment management."""

267

268

def get_attachment(self, attachment, headers=None, write_to=None, attachment_type=None):

269

"""

270

Retrieve document attachment.

271

272

Parameters:

273

- attachment (str): Attachment name

274

- headers (dict): Additional HTTP headers

275

- write_to (file-like): Stream attachment to file object

276

- attachment_type (str): Expected MIME type

277

278

Returns:

279

bytes | None: Attachment content (None if write_to specified)

280

281

Raises:

282

CloudantDocumentException: Attachment not found or retrieval failed

283

"""

284

285

def put_attachment(self, attachment, content_type, data, headers=None):

286

"""

287

Add or update document attachment.

288

289

Parameters:

290

- attachment (str): Attachment name

291

- content_type (str): MIME type of attachment

292

- data (bytes | file-like): Attachment content

293

- headers (dict): Additional HTTP headers

294

295

Returns:

296

dict: Upload response with updated _rev

297

298

Raises:

299

CloudantDocumentException: Upload failed

300

"""

301

302

def delete_attachment(self, attachment, headers=None):

303

"""

304

Delete document attachment.

305

306

Parameters:

307

- attachment (str): Attachment name to delete

308

- headers (dict): Additional HTTP headers

309

310

Returns:

311

dict: Deletion response with updated _rev

312

313

Raises:

314

CloudantDocumentException: Deletion failed

315

"""

316

```

317

318

### Context Manager Support

319

320

Automatic fetching and saving with context manager.

321

322

```python { .api }

323

class Document(dict):

324

"""Context manager support."""

325

326

def __enter__(self):

327

"""

328

Context manager entry - fetch document if it exists.

329

330

Returns:

331

Document: Self reference

332

"""

333

334

def __exit__(self, exc_type, exc_value, traceback):

335

"""

336

Context manager exit - save document if no exception.

337

338

Parameters:

339

- exc_type: Exception type (if any)

340

- exc_value: Exception value (if any)

341

- traceback: Exception traceback (if any)

342

343

Returns:

344

bool: False (don't suppress exceptions)

345

"""

346

```

347

348

### Bulk Operations

349

350

Batch operations for multiple documents.

351

352

```python { .api }

353

class CouchDatabase(dict):

354

"""Bulk document operations."""

355

356

def bulk_docs(self, docs):

357

"""

358

Perform bulk document operations.

359

360

Parameters:

361

- docs (list[dict]): List of documents to create/update/delete

362

Each doc can include _deleted: true for deletion

363

364

Returns:

365

list[dict]: List of operation results with _id, _rev, or error info

366

367

Raises:

368

CloudantDatabaseException: Bulk operation failed

369

"""

370

```

371

372

### Document Querying

373

374

Primary index and document iteration.

375

376

```python { .api }

377

class CouchDatabase(dict):

378

"""Document querying."""

379

380

def all_docs(self, **kwargs):

381

"""

382

Query primary index (_all_docs).

383

384

Parameters:

385

- include_docs (bool): Include document content

386

- startkey (str): Start key for range

387

- endkey (str): End key for range

388

- keys (list[str]): Specific document IDs to retrieve

389

- limit (int): Maximum results

390

- skip (int): Number of results to skip

391

- descending (bool): Reverse order

392

- inclusive_end (bool): Include endkey in results

393

394

Returns:

395

Result: Query result iterator

396

"""

397

398

def partitioned_all_docs(self, partition_key, **kwargs):

399

"""

400

Query primary index for specific partition.

401

402

Parameters:

403

- partition_key (str): Partition identifier

404

- **kwargs: Same options as all_docs()

405

406

Returns:

407

Result: Query result iterator

408

"""

409

```

410

411

## Usage Examples

412

413

### Basic Document Operations

414

415

```python

416

from cloudant import cloudant

417

418

with cloudant('user', 'pass', account='myaccount') as client:

419

db = client['my_database']

420

421

# Create document with specific ID

422

doc_data = {

423

'_id': 'user123',

424

'name': 'John Doe',

425

'email': 'john@example.com',

426

'tags': ['developer', 'python']

427

}

428

doc = db.create_document(doc_data)

429

print(f"Created: {doc['_id']} with rev {doc['_rev']}")

430

431

# Create document with auto-generated ID

432

new_doc = db.new_document()

433

new_doc['name'] = 'Jane Smith'

434

new_doc['role'] = 'designer'

435

new_doc.create()

436

437

# Access existing document

438

user_doc = db['user123']

439

440

# Check if document exists

441

if user_doc.exists():

442

# Fetch latest version

443

user_doc.fetch()

444

print(f"User: {user_doc['name']}")

445

446

# Update document

447

user_doc['last_login'] = '2023-01-15'

448

user_doc['tags'].append('admin')

449

user_doc.save()

450

451

# Delete document

452

user_doc.delete()

453

```

454

455

### Context Manager Usage

456

457

```python

458

from cloudant import cloudant

459

460

with cloudant('user', 'pass', account='myaccount') as client:

461

db = client['my_database']

462

463

# Automatic fetch and save

464

with db['user123'] as doc:

465

doc['last_updated'] = '2023-01-15'

466

doc['login_count'] = doc.get('login_count', 0) + 1

467

# Document is automatically saved on context exit

468

```

469

470

### Field Operations with Conflict Resolution

471

472

```python

473

from cloudant import cloudant

474

from cloudant.document import Document

475

476

with cloudant('user', 'pass', account='myaccount') as client:

477

db = client['my_database']

478

doc = db['user123']

479

480

# Append to list field with automatic conflict resolution

481

doc.update_field(Document.list_field_append, 'tags', 'admin')

482

483

# Remove from list field

484

doc.update_field(Document.list_field_remove, 'tags', 'developer')

485

486

# Set field value

487

doc.update_field(Document.field_set, 'status', 'active')

488

```

489

490

### Attachment Operations

491

492

```python

493

from cloudant import cloudant

494

495

with cloudant('user', 'pass', account='myaccount') as client:

496

db = client['my_database']

497

doc = db['user123']

498

499

# Add attachment

500

with open('profile.jpg', 'rb') as f:

501

attachment_data = f.read()

502

503

doc.put_attachment('profile_picture', 'image/jpeg', attachment_data)

504

505

# Retrieve attachment

506

image_data = doc.get_attachment('profile_picture')

507

508

# Save attachment to file

509

with open('downloaded_profile.jpg', 'wb') as f:

510

doc.get_attachment('profile_picture', write_to=f)

511

512

# Delete attachment

513

doc.delete_attachment('profile_picture')

514

```

515

516

### Bulk Operations

517

518

```python

519

from cloudant import cloudant

520

521

with cloudant('user', 'pass', account='myaccount') as client:

522

db = client['my_database']

523

524

# Bulk create/update documents

525

docs = [

526

{'_id': 'user1', 'name': 'Alice', 'role': 'admin'},

527

{'_id': 'user2', 'name': 'Bob', 'role': 'user'},

528

{'_id': 'user3', 'name': 'Carol', 'role': 'moderator'}

529

]

530

531

results = db.bulk_docs(docs)

532

for result in results:

533

if 'error' in result:

534

print(f"Error for {result['id']}: {result['error']}")

535

else:

536

print(f"Success: {result['id']} -> {result['rev']}")

537

538

# Bulk delete documents

539

delete_docs = [

540

{'_id': 'user1', '_rev': '1-abc123', '_deleted': True},

541

{'_id': 'user2', '_rev': '1-def456', '_deleted': True}

542

]

543

544

db.bulk_docs(delete_docs)

545

```

546

547

### Document Iteration and Querying

548

549

```python

550

from cloudant import cloudant

551

552

with cloudant('user', 'pass', account='myaccount') as client:

553

db = client['my_database']

554

555

# Iterate over all documents

556

for doc in db:

557

print(f"Document: {doc['_id']}")

558

559

# Query with all_docs

560

result = db.all_docs(include_docs=True, limit=10)

561

for row in result:

562

doc = row['doc']

563

print(f"ID: {doc['_id']}, Name: {doc.get('name', 'N/A')}")

564

565

# Query specific documents

566

user_ids = ['user1', 'user2', 'user3']

567

result = db.all_docs(keys=user_ids, include_docs=True)

568

for row in result:

569

if 'doc' in row:

570

print(f"Found user: {row['doc']['name']}")

571

572

# Range query

573

result = db.all_docs(

574

startkey='user',

575

endkey='user\ufff0', # Unicode high character for prefix matching

576

include_docs=True

577

)

578

for row in result:

579

print(f"User document: {row['doc']['_id']}")

580

```

581

582

### Partitioned Document Operations (Cloudant)

583

584

```python

585

from cloudant import cloudant

586

587

with cloudant('user', 'pass', account='myaccount') as client:

588

# Create partitioned database

589

db = client.create_database('partitioned_db', partitioned=True)

590

591

# Create document in partition

592

doc = db.create_document({

593

'_id': 'user123:profile', # partition_key:document_id format

594

'name': 'John Doe',

595

'partition': 'user123'

596

})

597

598

# Query partition

599

result = db.partitioned_all_docs('user123', include_docs=True)

600

for row in result:

601

print(f"Partition doc: {row['doc']['_id']}")

602

```

603

604

## Error Handling

605

606

Document operations can raise `CloudantDocumentException`:

607

608

```python

609

from cloudant import cloudant

610

from cloudant.error import CloudantDocumentException

611

612

with cloudant('user', 'pass', account='myaccount') as client:

613

db = client['my_database']

614

615

try:

616

# Try to fetch non-existent document

617

doc = db['non_existent']

618

doc.fetch()

619

except CloudantDocumentException as e:

620

print(f"Document not found: {e}")

621

622

try:

623

# Try to save document with stale revision

624

doc = db['user123']

625

doc.fetch()

626

doc['_rev'] = '1-old_revision' # Simulate stale revision

627

doc['name'] = 'Updated Name'

628

doc.save()

629

except CloudantDocumentException as e:

630

print(f"Conflict error: {e}")

631

# Fetch latest and retry

632

doc.fetch()

633

doc['name'] = 'Updated Name'

634

doc.save()

635

```