or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

analytics-operations.mdasync-operations.mdcluster-operations.mddocument-operations.mdindex.mdmanagement-operations.mdn1ql-queries.mdsearch-operations.mdsubdocument-operations.mdview-operations.md

subdocument-operations.mddocs/

0

# Subdocument Operations

1

2

Efficient operations on specific paths within JSON documents without retrieving or replacing entire documents. Enables atomic mutations and lookups on document fragments for improved performance and reduced network overhead.

3

4

## Capabilities

5

6

### Document Path Operations

7

8

Perform operations on specific JSON paths within documents.

9

10

```python { .api }

11

class CBCollection:

12

def lookup_in(self, key: str, spec: List[Spec], options: LookupInOptions = None) -> LookupInResult:

13

"""

14

Perform subdocument lookup operations.

15

16

Args:

17

key (str): Document key

18

spec (List[Spec]): List of lookup specifications

19

options (LookupInOptions, optional): Lookup options

20

21

Returns:

22

LookupInResult: Results for each lookup operation

23

24

Raises:

25

DocumentNotFoundException: If document doesn't exist

26

PathNotFoundException: If specified path doesn't exist

27

"""

28

29

def mutate_in(self, key: str, spec: List[Spec], options: MutateInOptions = None) -> MutateInResult:

30

"""

31

Perform subdocument mutation operations.

32

33

Args:

34

key (str): Document key

35

spec (List[Spec]): List of mutation specifications

36

options (MutateInOptions, optional): Mutation options

37

38

Returns:

39

MutateInResult: Results for each mutation operation

40

41

Raises:

42

DocumentNotFoundException: If document doesn't exist

43

PathExistsException: If path already exists (for insert operations)

44

PathNotFoundException: If path doesn't exist (for replace operations)

45

"""

46

```

47

48

### Lookup Specifications

49

50

Specify paths and operations for document lookups.

51

52

```python { .api }

53

import couchbase.subdocument as SD

54

55

class Spec:

56

@staticmethod

57

def get(path: str, xattr: bool = False) -> Spec:

58

"""

59

Get value at path.

60

61

Args:

62

path (str): JSON path

63

xattr (bool): Whether path refers to extended attribute

64

65

Returns:

66

Spec: Lookup specification

67

"""

68

69

@staticmethod

70

def exists(path: str, xattr: bool = False) -> Spec:

71

"""

72

Check if path exists.

73

74

Args:

75

path (str): JSON path

76

xattr (bool): Whether path refers to extended attribute

77

78

Returns:

79

Spec: Existence check specification

80

"""

81

82

@staticmethod

83

def count(path: str, xattr: bool = False) -> Spec:

84

"""

85

Count elements in array at path.

86

87

Args:

88

path (str): JSON path to array

89

xattr (bool): Whether path refers to extended attribute

90

91

Returns:

92

Spec: Count specification

93

"""

94

95

@staticmethod

96

def get_full() -> Spec:

97

"""

98

Get entire document.

99

100

Returns:

101

Spec: Full document retrieval specification

102

"""

103

```

104

105

### Mutation Specifications

106

107

Specify paths and operations for document mutations.

108

109

```python { .api }

110

class Spec:

111

@staticmethod

112

def replace(path: str, value: Any, xattr: bool = False) -> Spec:

113

"""

114

Replace value at path.

115

116

Args:

117

path (str): JSON path

118

value (Any): New value

119

xattr (bool): Whether path refers to extended attribute

120

121

Returns:

122

Spec: Replace specification

123

"""

124

125

@staticmethod

126

def upsert(path: str, value: Any, xattr: bool = False, create_path: bool = False) -> Spec:

127

"""

128

Insert or replace value at path.

129

130

Args:

131

path (str): JSON path

132

value (Any): Value to set

133

xattr (bool): Whether path refers to extended attribute

134

create_path (bool): Create intermediate paths if needed

135

136

Returns:

137

Spec: Upsert specification

138

"""

139

140

@staticmethod

141

def insert(path: str, value: Any, xattr: bool = False, create_path: bool = False) -> Spec:

142

"""

143

Insert value at path (must not exist).

144

145

Args:

146

path (str): JSON path

147

value (Any): Value to insert

148

xattr (bool): Whether path refers to extended attribute

149

create_path (bool): Create intermediate paths if needed

150

151

Returns:

152

Spec: Insert specification

153

"""

154

155

@staticmethod

156

def remove(path: str, xattr: bool = False) -> Spec:

157

"""

158

Remove value at path.

159

160

Args:

161

path (str): JSON path

162

xattr (bool): Whether path refers to extended attribute

163

164

Returns:

165

Spec: Remove specification

166

"""

167

```

168

169

### Array Operations

170

171

Specialized operations for working with JSON arrays.

172

173

```python { .api }

174

class Spec:

175

@staticmethod

176

def array_append(path: str, *values: Any, xattr: bool = False, create_path: bool = False) -> Spec:

177

"""

178

Append values to end of array.

179

180

Args:

181

path (str): JSON path to array

182

*values: Values to append

183

xattr (bool): Whether path refers to extended attribute

184

create_path (bool): Create array if path doesn't exist

185

186

Returns:

187

Spec: Array append specification

188

"""

189

190

@staticmethod

191

def array_prepend(path: str, *values: Any, xattr: bool = False, create_path: bool = False) -> Spec:

192

"""

193

Prepend values to beginning of array.

194

195

Args:

196

path (str): JSON path to array

197

*values: Values to prepend

198

xattr (bool): Whether path refers to extended attribute

199

create_path (bool): Create array if path doesn't exist

200

201

Returns:

202

Spec: Array prepend specification

203

"""

204

205

@staticmethod

206

def array_insert(path: str, *values: Any, xattr: bool = False) -> Spec:

207

"""

208

Insert values at specific array index.

209

210

Args:

211

path (str): JSON path with array index (e.g., "items[2]")

212

*values: Values to insert

213

xattr (bool): Whether path refers to extended attribute

214

215

Returns:

216

Spec: Array insert specification

217

"""

218

219

@staticmethod

220

def array_add_unique(path: str, value: Any, xattr: bool = False, create_path: bool = False) -> Spec:

221

"""

222

Add value to array if not already present.

223

224

Args:

225

path (str): JSON path to array

226

value (Any): Value to add

227

xattr (bool): Whether path refers to extended attribute

228

create_path (bool): Create array if path doesn't exist

229

230

Returns:

231

Spec: Array add unique specification

232

"""

233

```

234

235

### Counter Operations

236

237

Atomic counter operations on numeric values within documents.

238

239

```python { .api }

240

class Spec:

241

@staticmethod

242

def increment(path: str, delta: int = 1, xattr: bool = False, create_path: bool = False) -> Spec:

243

"""

244

Increment numeric value at path.

245

246

Args:

247

path (str): JSON path to numeric value

248

delta (int): Increment amount (default: 1)

249

xattr (bool): Whether path refers to extended attribute

250

create_path (bool): Create path with initial value if needed

251

252

Returns:

253

Spec: Increment specification

254

"""

255

256

@staticmethod

257

def decrement(path: str, delta: int = 1, xattr: bool = False, create_path: bool = False) -> Spec:

258

"""

259

Decrement numeric value at path.

260

261

Args:

262

path (str): JSON path to numeric value

263

delta (int): Decrement amount (default: 1)

264

xattr (bool): Whether path refers to extended attribute

265

create_path (bool): Create path with initial value if needed

266

267

Returns:

268

Spec: Decrement specification

269

"""

270

```

271

272

## Operation Options

273

274

```python { .api }

275

class LookupInOptions:

276

def __init__(self, timeout: timedelta = None,

277

access_deleted: bool = False):

278

"""

279

Options for subdocument lookup operations.

280

281

Args:

282

timeout (timedelta, optional): Operation timeout

283

access_deleted (bool): Access tombstoned (deleted) documents

284

"""

285

286

class MutateInOptions:

287

def __init__(self, timeout: timedelta = None,

288

expiry: timedelta = None,

289

durability: Durability = None,

290

cas: int = None,

291

upsert_document: bool = False,

292

access_deleted: bool = False):

293

"""

294

Options for subdocument mutation operations.

295

296

Args:

297

timeout (timedelta, optional): Operation timeout

298

expiry (timedelta, optional): Document expiration

299

durability (Durability, optional): Durability requirements

300

cas (int, optional): CAS value for optimistic locking

301

upsert_document (bool): Create document if it doesn't exist

302

access_deleted (bool): Access tombstoned (deleted) documents

303

"""

304

```

305

306

## Result Types

307

308

```python { .api }

309

class LookupInResult:

310

def content_as(self, index: int, target_type: type):

311

"""

312

Get content of lookup operation at index.

313

314

Args:

315

index (int): Operation index

316

target_type (type): Target type for content

317

318

Returns:

319

Content converted to target type

320

"""

321

322

def exists(self, index: int) -> bool:

323

"""Check if path exists for operation at index."""

324

325

@property

326

def cas(self) -> int:

327

"""Document CAS value."""

328

329

class MutateInResult:

330

def content_as(self, index: int, target_type: type):

331

"""

332

Get content of mutation operation at index.

333

334

Args:

335

index (int): Operation index

336

target_type (type): Target type for content

337

338

Returns:

339

Content converted to target type

340

"""

341

342

@property

343

def cas(self) -> int:

344

"""New document CAS value."""

345

346

@property

347

def mutation_token(self) -> MutationToken:

348

"""Mutation token for consistency."""

349

```

350

351

## Usage Examples

352

353

### Basic Subdocument Operations

354

355

```python

356

import couchbase.subdocument as SD

357

358

# Document structure

359

doc = {

360

"name": "John Doe",

361

"age": 30,

362

"address": {

363

"street": "123 Main St",

364

"city": "San Francisco"

365

},

366

"hobbies": ["reading", "cycling"]

367

}

368

369

collection.upsert("user::123", doc)

370

371

# Lookup specific fields

372

result = collection.lookup_in("user::123", [

373

SD.get("name"),

374

SD.get("address.city"),

375

SD.exists("phone"),

376

SD.count("hobbies")

377

])

378

379

name = result.content_as(0, str)

380

city = result.content_as(1, str)

381

has_phone = result.exists(2)

382

hobby_count = result.content_as(3, int)

383

384

print(f"Name: {name}, City: {city}")

385

print(f"Has phone: {has_phone}, Hobbies: {hobby_count}")

386

```

387

388

### Subdocument Mutations

389

390

```python

391

# Update specific fields

392

collection.mutate_in("user::123", [

393

SD.replace("age", 31),

394

SD.upsert("address.zipcode", "94105"),

395

SD.array_append("hobbies", "photography"),

396

SD.increment("login_count", 1)

397

])

398

399

# Insert new nested object

400

collection.mutate_in("user::123", [

401

SD.insert("preferences", {"theme": "dark", "notifications": True})

402

])

403

404

# Remove field

405

collection.mutate_in("user::123", [

406

SD.remove("temporary_field")

407

])

408

```

409

410

### Array Operations

411

412

```python

413

# Working with arrays

414

collection.mutate_in("user::123", [

415

SD.array_append("hobbies", "gaming", "cooking"),

416

SD.array_prepend("hobbies", "traveling"),

417

SD.array_insert("hobbies[2]", "swimming"),

418

SD.array_add_unique("tags", "vip")

419

])

420

421

# Check array contents

422

result = collection.lookup_in("user::123", [

423

SD.get("hobbies"),

424

SD.count("hobbies"),

425

SD.get("hobbies[0]") # First element

426

])

427

428

all_hobbies = result.content_as(0, list)

429

hobby_count = result.content_as(1, int)

430

first_hobby = result.content_as(2, str)

431

```

432

433

### Counter Operations

434

435

```python

436

# Initialize counters

437

collection.mutate_in("stats::global", [

438

SD.upsert("page_views", 0, create_path=True),

439

SD.upsert("user_count", 100, create_path=True)

440

], MutateInOptions(upsert_document=True))

441

442

# Increment counters atomically

443

collection.mutate_in("stats::global", [

444

SD.increment("page_views", 1),

445

SD.increment("user_count", 1),

446

SD.increment("api_calls", 5)

447

])

448

449

# Get current values

450

result = collection.lookup_in("stats::global", [

451

SD.get("page_views"),

452

SD.get("user_count")

453

])

454

455

views = result.content_as(0, int)

456

users = result.content_as(1, int)

457

```

458

459

### Document Creation with Subdocument

460

461

```python

462

# Create document using subdocument operations

463

collection.mutate_in("user::456", [

464

SD.upsert("name", "Alice Smith"),

465

SD.upsert("profile.bio", "Software engineer"),

466

SD.upsert("profile.skills", ["Python", "JavaScript"]),

467

SD.upsert("stats.login_count", 0)

468

], MutateInOptions(upsert_document=True))

469

```

470

471

### Extended Attributes (XAttrs)

472

473

```python

474

# Work with extended attributes (metadata)

475

collection.mutate_in("user::123", [

476

SD.upsert("_metadata.created_by", "system", xattr=True),

477

SD.upsert("_metadata.version", 1, xattr=True),

478

SD.replace("name", "John Smith") # Regular document update

479

])

480

481

# Lookup extended attributes

482

result = collection.lookup_in("user::123", [

483

SD.get("_metadata", xattr=True),

484

SD.get("name")

485

])

486

487

metadata = result.content_as(0, dict)

488

name = result.content_as(1, str)

489

```

490

491

### Error Handling

492

493

```python

494

from couchbase.exceptions import PathNotFoundException, PathExistsException

495

496

try:

497

collection.mutate_in("user::123", [

498

SD.replace("nonexistent.field", "value"),

499

SD.insert("existing.field", "new_value")

500

])

501

except PathNotFoundException as e:

502

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

503

except PathExistsException as e:

504

print(f"Path already exists: {e}")

505

```