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

views-design-documents.mddocs/

0

# Views and Design Documents

1

2

Manage MapReduce views, list functions, show functions, and update handlers through design documents. Design documents are special documents that contain application code for database operations including views, indexes, and server-side functions.

3

4

## Capabilities

5

6

### Design Document Management

7

8

Access and manage design documents containing views and functions.

9

10

```python { .api }

11

class CouchDatabase(dict):

12

"""Design document access methods."""

13

14

def design_documents(self):

15

"""

16

Get all design documents in the database.

17

18

Returns:

19

dict: All design documents keyed by design document ID

20

"""

21

22

def list_design_documents(self):

23

"""

24

List design document names.

25

26

Returns:

27

list[str]: Design document IDs (without _design/ prefix)

28

"""

29

30

def get_design_document(self, ddoc_id):

31

"""

32

Get specific design document.

33

34

Parameters:

35

- ddoc_id (str): Design document ID (without _design/ prefix)

36

37

Returns:

38

DesignDocument: Design document instance

39

40

Raises:

41

CloudantDesignDocumentException: Design document not found

42

"""

43

```

44

45

### DesignDocument Class

46

47

Special document type for managing views, indexes, and functions.

48

49

```python { .api }

50

class DesignDocument(Document):

51

"""

52

Design document containing views, indexes, and server-side functions.

53

"""

54

55

def __init__(self, database, document_id=None, partitioned=False):

56

"""

57

Initialize design document.

58

59

Parameters:

60

- database (CouchDatabase | CloudantDatabase): Parent database

61

- document_id (str): Design document ID (without _design/ prefix)

62

- partitioned (bool): Whether views are partitioned

63

"""

64

65

@property

66

def views(self):

67

"""

68

MapReduce views in this design document.

69

70

Returns:

71

dict: View definitions with map/reduce functions

72

"""

73

74

@property

75

def shows(self):

76

"""

77

Show functions for formatting documents.

78

79

Returns:

80

dict: Show function definitions

81

"""

82

83

@property

84

def lists(self):

85

"""

86

List functions for formatting view results.

87

88

Returns:

89

dict: List function definitions

90

"""

91

92

@property

93

def updates(self):

94

"""

95

Update handlers for document modifications.

96

97

Returns:

98

dict: Update handler definitions

99

"""

100

101

@property

102

def filters(self):

103

"""

104

Filter functions for change feeds.

105

106

Returns:

107

dict: Filter function definitions

108

"""

109

110

@property

111

def validate_doc_update(self):

112

"""

113

Document validation function.

114

115

Returns:

116

str: Validation function JavaScript code

117

"""

118

119

@property

120

def rewrites(self):

121

"""

122

URL rewrite rules.

123

124

Returns:

125

list[dict]: Rewrite rule definitions

126

"""

127

128

@property

129

def indexes(self):

130

"""

131

Search indexes (Cloudant only).

132

133

Returns:

134

dict: Search index definitions

135

"""

136

```

137

138

### View Class

139

140

Individual MapReduce view management.

141

142

```python { .api }

143

class View:

144

"""

145

MapReduce view within a design document.

146

"""

147

148

def __init__(self, design_document, view_name, **kwargs):

149

"""

150

Initialize view instance.

151

152

Parameters:

153

- design_document (DesignDocument): Parent design document

154

- view_name (str): View name within design document

155

- **kwargs: View options and parameters

156

"""

157

158

def __call__(self, **kwargs):

159

"""

160

Execute view query.

161

162

Parameters:

163

- key: Single key to query

164

- keys (list): Multiple keys to query

165

- startkey: Start of key range

166

- endkey: End of key range

167

- startkey_docid (str): Start document ID for pagination

168

- endkey_docid (str): End document ID for pagination

169

- limit (int): Maximum results

170

- skip (int): Number of results to skip

171

- descending (bool): Reverse sort order

172

- group (bool): Group results by key

173

- group_level (int): Group level for complex keys

174

- reduce (bool): Use reduce function (default: True if available)

175

- include_docs (bool): Include document content

176

- inclusive_end (bool): Include endkey in results

177

- update_seq (bool): Include update sequence in response

178

- conflicts (bool): Include conflict information

179

- attachments (bool): Include attachment stubs

180

- att_encoding_info (bool): Include attachment encoding info

181

182

Returns:

183

Result: View result iterator

184

185

Raises:

186

CloudantViewException: View query failed

187

"""

188

189

def custom_result(self, **options):

190

"""

191

Execute view with custom result options.

192

193

Parameters:

194

- **options: Result collection options

195

196

Returns:

197

Result: Custom result iterator

198

"""

199

200

@property

201

def result(self):

202

"""Default view result collection"""

203

204

@property

205

def map_function(self):

206

"""

207

JavaScript map function code.

208

209

Returns:

210

str: Map function JavaScript code

211

"""

212

213

@property

214

def reduce_function(self):

215

"""

216

JavaScript reduce function code.

217

218

Returns:

219

str | None: Reduce function JavaScript code or None

220

"""

221

```

222

223

### View Execution Methods

224

225

Database methods for executing views.

226

227

```python { .api }

228

class CouchDatabase(dict):

229

"""View execution methods."""

230

231

def get_view_result(self, ddoc_id, view_name, raw_result=False, **kwargs):

232

"""

233

Execute MapReduce view and return results.

234

235

Parameters:

236

- ddoc_id (str): Design document ID (without _design/ prefix)

237

- view_name (str): View name within design document

238

- raw_result (bool): Return raw response without processing

239

- **kwargs: View query parameters (same as View.__call__)

240

241

Returns:

242

Result | dict: View results or raw response

243

244

Raises:

245

CloudantViewException: View execution failed

246

"""

247

248

def get_partitioned_view_result(self, partition_key, ddoc_id, view_name, raw_result=False, **kwargs):

249

"""

250

Execute view within specific partition.

251

252

Parameters:

253

- partition_key (str): Partition identifier

254

- ddoc_id (str): Design document ID

255

- view_name (str): View name

256

- raw_result (bool): Return raw response

257

- **kwargs: View query parameters

258

259

Returns:

260

Result | dict: Partitioned view results

261

"""

262

```

263

264

### List and Show Functions

265

266

Server-side formatting functions.

267

268

```python { .api }

269

class CouchDatabase(dict):

270

"""List and show function execution."""

271

272

def get_list_function_result(self, ddoc_id, list_name, view_name, **kwargs):

273

"""

274

Execute list function to format view results.

275

276

Parameters:

277

- ddoc_id (str): Design document ID

278

- list_name (str): List function name

279

- view_name (str): View name to format

280

- **kwargs: View parameters and list options

281

282

Returns:

283

str: Formatted output from list function

284

285

Raises:

286

CloudantDesignDocumentException: List function execution failed

287

"""

288

289

def get_show_function_result(self, ddoc_id, show_name, doc_id):

290

"""

291

Execute show function to format document.

292

293

Parameters:

294

- ddoc_id (str): Design document ID

295

- show_name (str): Show function name

296

- doc_id (str): Document ID to format

297

298

Returns:

299

str: Formatted output from show function

300

301

Raises:

302

CloudantDesignDocumentException: Show function execution failed

303

"""

304

```

305

306

### Update Handlers

307

308

Server-side document update functions.

309

310

```python { .api }

311

class CouchDatabase(dict):

312

"""Update handler execution."""

313

314

def update_handler_result(self, ddoc_id, handler_name, doc_id=None, data=None, **params):

315

"""

316

Execute update handler function.

317

318

Parameters:

319

- ddoc_id (str): Design document ID

320

- handler_name (str): Update handler name

321

- doc_id (str): Document ID to update (optional for create)

322

- data (dict | str): Request body data

323

- **params: Additional URL parameters

324

325

Returns:

326

dict: Update handler response

327

328

Raises:

329

CloudantDesignDocumentException: Update handler execution failed

330

"""

331

```

332

333

## Usage Examples

334

335

### Creating Design Documents

336

337

```python

338

from cloudant import cloudant

339

from cloudant.design_document import DesignDocument

340

341

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

342

db = client['my_database']

343

344

# Create design document with views

345

ddoc = DesignDocument(db, 'user_views')

346

347

# Add MapReduce view

348

ddoc['views'] = {

349

'by_status': {

350

'map': '''

351

function(doc) {

352

if (doc.type === 'user') {

353

emit(doc.status, {

354

name: doc.name,

355

email: doc.email,

356

created: doc.created_date

357

});

358

}

359

}

360

'''

361

},

362

'count_by_department': {

363

'map': '''

364

function(doc) {

365

if (doc.type === 'user' && doc.department) {

366

emit(doc.department, 1);

367

}

368

}

369

''',

370

'reduce': '_count' # Built-in reduce function

371

}

372

}

373

374

# Add show function

375

ddoc['shows'] = {

376

'user_profile': '''

377

function(doc, req) {

378

if (!doc) {

379

return {

380

code: 404,

381

body: 'User not found'

382

};

383

}

384

385

var html = '<h1>' + doc.name + '</h1>';

386

html += '<p>Email: ' + doc.email + '</p>';

387

html += '<p>Status: ' + doc.status + '</p>';

388

389

return {

390

headers: {'Content-Type': 'text/html'},

391

body: html

392

};

393

}

394

'''

395

}

396

397

# Add list function

398

ddoc['lists'] = {

399

'user_csv': '''

400

function(head, req) {

401

var row;

402

start({headers: {'Content-Type': 'text/csv'}});

403

send('name,email,status\\n');

404

405

while (row = getRow()) {

406

var user = row.value;

407

send(user.name + ',' + user.email + ',' + row.key + '\\n');

408

}

409

}

410

'''

411

}

412

413

# Add update handler

414

ddoc['updates'] = {

415

'status_update': '''

416

function(doc, req) {

417

if (!doc) {

418

return [null, {

419

code: 404,

420

body: 'Document not found'

421

}];

422

}

423

424

var new_status = req.form.status;

425

if (new_status) {

426

doc.status = new_status;

427

doc.updated_date = new Date().toISOString();

428

429

return [doc, {

430

code: 200,

431

headers: {'Content-Type': 'application/json'},

432

body: JSON.stringify({status: 'updated'})

433

}];

434

}

435

436

return [null, {

437

code: 400,

438

body: 'Status parameter required'

439

}];

440

}

441

'''

442

}

443

444

# Save design document

445

ddoc.save()

446

print(f"Created design document: {ddoc['_id']}")

447

```

448

449

### Querying Views

450

451

```python

452

from cloudant import cloudant

453

454

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

455

db = client['my_database']

456

457

# Query view with specific key

458

result = db.get_view_result('user_views', 'by_status', key='active')

459

for row in result:

460

user = row['value']

461

print(f"Active user: {user['name']} ({user['email']})")

462

463

# Query view with key range

464

result = db.get_view_result(

465

'user_views',

466

'by_status',

467

startkey='active',

468

endkey='pending',

469

include_docs=True

470

)

471

472

for row in result:

473

print(f"User {row['key']}: {row['doc']['name']}")

474

475

# Query with multiple keys

476

statuses = ['active', 'pending', 'suspended']

477

result = db.get_view_result('user_views', 'by_status', keys=statuses)

478

479

# Reduced view (count)

480

result = db.get_view_result('user_views', 'count_by_department')

481

for row in result:

482

print(f"Department {row['key']}: {row['value']} users")

483

```

484

485

### Using View Objects

486

487

```python

488

from cloudant import cloudant

489

from cloudant.view import View

490

491

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

492

db = client['my_database']

493

ddoc = db.get_design_document('user_views')

494

495

# Create reusable view object

496

status_view = View(ddoc, 'by_status')

497

498

# Query active users

499

active_users = status_view(key='active', include_docs=True)

500

for row in active_users:

501

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

502

503

# Query with custom result options

504

paginated_result = status_view.custom_result(

505

limit=10,

506

skip=0,

507

key='active'

508

)

509

510

for row in paginated_result:

511

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

512

```

513

514

### Complex View Queries

515

516

```python

517

from cloudant import cloudant

518

519

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

520

db = client['my_database']

521

522

# Pagination with startkey_docid

523

last_key = None

524

last_docid = None

525

page_size = 25

526

527

while True:

528

params = {

529

'limit': page_size + 1, # Get one extra to check for more

530

'include_docs': True

531

}

532

533

if last_key is not None:

534

params['startkey'] = last_key

535

params['startkey_docid'] = last_docid

536

params['skip'] = 1 # Skip the last doc from previous page

537

538

result = db.get_view_result('user_views', 'by_status', **params)

539

rows = list(result)

540

541

if not rows:

542

break

543

544

# Process current page (excluding extra row)

545

page_rows = rows[:page_size]

546

for row in page_rows:

547

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

548

549

# Check if there are more pages

550

if len(rows) <= page_size:

551

break

552

553

# Set pagination markers for next page

554

last_row = rows[page_size - 1]

555

last_key = last_row['key']

556

last_docid = last_row['id']

557

558

# Group reduce queries

559

result = db.get_view_result(

560

'user_views',

561

'count_by_department',

562

group=True,

563

group_level=1

564

)

565

566

for row in result:

567

print(f"Department: {row['key']}, Count: {row['value']}")

568

```

569

570

### List and Show Functions

571

572

```python

573

from cloudant import cloudant

574

575

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

576

db = client['my_database']

577

578

# Execute show function

579

html_output = db.get_show_function_result(

580

'user_views',

581

'user_profile',

582

'user123'

583

)

584

print("HTML Profile:", html_output)

585

586

# Execute list function

587

csv_output = db.get_list_function_result(

588

'user_views',

589

'user_csv',

590

'by_status',

591

key='active'

592

)

593

print("CSV Export:", csv_output)

594

```

595

596

### Update Handlers

597

598

```python

599

from cloudant import cloudant

600

import json

601

602

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

603

db = client['my_database']

604

605

# Execute update handler

606

response = db.update_handler_result(

607

'user_views',

608

'status_update',

609

'user123',

610

data={'status': 'suspended'}

611

)

612

613

print(f"Update response: {response}")

614

615

# Update handler for new document

616

response = db.update_handler_result(

617

'user_views',

618

'create_user',

619

data=json.dumps({

620

'name': 'New User',

621

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

622

'status': 'pending'

623

})

624

)

625

```

626

627

### Partitioned Views (Cloudant)

628

629

```python

630

from cloudant import cloudant

631

632

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

633

# Use partitioned database

634

db = client['partitioned_database']

635

636

# Create partitioned design document

637

ddoc = db.get_design_document('partition_views')

638

ddoc['views'] = {

639

'by_activity_type': {

640

'map': '''

641

function(doc) {

642

if (doc.type === 'activity') {

643

emit(doc.activity_type, {

644

timestamp: doc.timestamp,

645

details: doc.details

646

});

647

}

648

}

649

'''

650

}

651

}

652

ddoc['options'] = {'partitioned': True}

653

ddoc.save()

654

655

# Query view within partition

656

result = db.get_partitioned_view_result(

657

'user123', # partition key

658

'partition_views',

659

'by_activity_type',

660

key='login',

661

limit=10

662

)

663

664

for row in result:

665

activity = row['value']

666

print(f"Login activity: {activity['timestamp']}")

667

```

668

669

### View Performance Optimization

670

671

```python

672

from cloudant import cloudant

673

674

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

675

db = client['my_database']

676

677

# Query view without reduce for better performance on large datasets

678

result = db.get_view_result(

679

'user_views',

680

'count_by_department',

681

reduce=False, # Skip reduce function

682

include_docs=False # Don't fetch full documents

683

)

684

685

# Count manually if needed

686

department_counts = {}

687

for row in result:

688

dept = row['key']

689

department_counts[dept] = department_counts.get(dept, 0) + 1

690

691

# Use stale views for better performance (eventual consistency)

692

result = db.get_view_result(

693

'user_views',

694

'by_status',

695

stale='ok', # Don't wait for index updates

696

key='active'

697

)

698

```

699

700

## Error Handling

701

702

View and design document operations can raise specific exceptions:

703

704

```python

705

from cloudant import cloudant

706

from cloudant.error import (

707

CloudantDesignDocumentException,

708

CloudantViewException

709

)

710

711

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

712

db = client['my_database']

713

714

try:

715

# Query non-existent view

716

result = db.get_view_result('missing_ddoc', 'missing_view')

717

except CloudantViewException as e:

718

print(f"View query failed: {e}")

719

720

try:

721

# Execute non-existent show function

722

output = db.get_show_function_result('ddoc', 'missing_show', 'doc123')

723

except CloudantDesignDocumentException as e:

724

print(f"Show function failed: {e}")

725

726

try:

727

# Create design document with invalid JavaScript

728

ddoc = db.get_design_document('invalid_views')

729

ddoc['views'] = {

730

'bad_view': {

731

'map': 'invalid javascript code here'

732

}

733

}

734

ddoc.save()

735

except CloudantDesignDocumentException as e:

736

print(f"Design document save failed: {e}")

737

```