or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-querying.mdcollection-operations.mddatabase-management.mddynamic-views.mdindex.mdpersistence-adapters.md

collection-operations.mddocs/

0

# Collection Operations

1

2

Document storage and retrieval with powerful querying, indexing, and aggregation capabilities. Collections are the primary containers for documents in LokiJS.

3

4

## Capabilities

5

6

### Collection Constructor

7

8

Creates a new collection with optional configuration for indexing and behavior.

9

10

```javascript { .api }

11

/**

12

* Creates a new collection

13

* @param name - Collection name

14

* @param options - Collection configuration options

15

*/

16

constructor Collection(name: string, options?: CollectionOptions);

17

18

interface CollectionOptions {

19

/** Array of field names that should be unique */

20

unique?: string[];

21

/** Array of field names for exact matching indexes */

22

exact?: string[];

23

/** Array of field names to create binary indexes on */

24

indices?: string[];

25

/** Enable adaptive binary indices */

26

adaptiveBinaryIndices?: boolean;

27

/** Enable async listeners */

28

asyncListeners?: boolean;

29

/** Disable meta properties ($loki, meta) */

30

disableMeta?: boolean;

31

/** Disable changes API tracking */

32

disableChangesApi?: boolean;

33

/** Disable delta changes API */

34

disableDeltaChangesApi?: boolean;

35

/** Enable auto-update for live objects */

36

autoupdate?: boolean;

37

/** Clone objects when retrieving */

38

clone?: boolean;

39

/** Clone method ('parse-stringify', 'jquery-extend-deep', 'shallow', 'shallow-assign') */

40

cloneMethod?: string;

41

/** Enable transactional mode */

42

transactional?: boolean;

43

/** Time to live in milliseconds */

44

ttl?: number;

45

/** TTL interval check in milliseconds */

46

ttlInterval?: number;

47

}

48

```

49

50

### Basic CRUD Operations

51

52

Fundamental create, read, update, and delete operations for documents.

53

54

```javascript { .api }

55

/**

56

* Insert one or more documents into the collection

57

* @param doc - Document or array of documents to insert

58

* @returns Inserted document(s) with generated $loki id

59

*/

60

insert(doc: object | object[]): object | object[];

61

62

/**

63

* Update an existing document

64

* @param doc - Document to update (must have $loki id)

65

* @returns Updated document

66

*/

67

update(doc: object): object;

68

69

/**

70

* Remove a document from the collection

71

* @param doc - Document to remove (must have $loki id)

72

* @returns Removed document

73

*/

74

remove(doc: object): object;

75

76

/**

77

* Remove multiple documents in batch

78

* @param batch - Array of documents to remove

79

*/

80

removeBatch(batch: object[]): void;

81

82

/**

83

* Remove all documents matching query

84

* @param query - Query object to match documents for removal

85

*/

86

removeWhere(query: object): void;

87

88

/**

89

* Clear all documents from collection

90

* @param options - Clear options

91

*/

92

clear(options?: object): void;

93

```

94

95

**Usage Examples:**

96

97

```javascript

98

const users = db.addCollection('users');

99

100

// Insert single document

101

const user = users.insert({ name: 'Alice', age: 25, email: 'alice@example.com' });

102

console.log(user.$loki); // Auto-generated ID

103

104

// Insert multiple documents

105

const newUsers = users.insert([

106

{ name: 'Bob', age: 30, email: 'bob@example.com' },

107

{ name: 'Charlie', age: 35, email: 'charlie@example.com' }

108

]);

109

110

// Update document

111

user.age = 26;

112

users.update(user);

113

114

// Remove document

115

users.remove(user);

116

117

// Remove documents matching criteria

118

users.removeWhere({ age: { $lt: 30 } });

119

120

// Clear all documents

121

users.clear();

122

```

123

124

### Querying Operations

125

126

Find and retrieve documents using various query methods.

127

128

```javascript { .api }

129

/**

130

* Find documents matching query criteria

131

* @param query - Query object (empty object or undefined returns all)

132

* @returns Array of matching documents

133

*/

134

find(query?: object): object[];

135

136

/**

137

* Find first document matching query criteria

138

* @param query - Query object

139

* @returns First matching document or null

140

*/

141

findOne(query?: object): object | null;

142

143

/**

144

* Get document by $loki id

145

* @param id - Document $loki id

146

* @param returnPosition - If true, return array index instead of document

147

* @returns Document or index, or null if not found

148

*/

149

get(id: number, returnPosition?: boolean): object | number | null;

150

151

/**

152

* Find document by indexed field value (fastest lookup)

153

* @param field - Indexed field name

154

* @param value - Field value to search for

155

* @returns First matching document or null

156

*/

157

by(field: string, value: any): object | null;

158

159

/**

160

* Filter documents using a custom function

161

* @param fun - Filter function returning boolean

162

* @returns Array of documents where function returns true

163

*/

164

where(fun: (obj: object) => boolean): object[];

165

```

166

167

**Usage Examples:**

168

169

```javascript

170

// Find all active users

171

const activeUsers = users.find({ active: true });

172

173

// Find users over 25

174

const matureUsers = users.find({ age: { $gt: 25 } });

175

176

// Find first user named 'Alice'

177

const alice = users.findOne({ name: 'Alice' });

178

179

// Get document by ID

180

const user = users.get(5);

181

182

// Find by indexed field

183

const user = users.by('email', 'alice@example.com');

184

185

// Custom filter function

186

const youngActiveUsers = users.where(obj => obj.age < 30 && obj.active);

187

```

188

189

### Advanced Finding

190

191

Advanced search capabilities including templates and compound operations.

192

193

```javascript { .api }

194

/**

195

* Find documents matching template object

196

* @param template - Template object to match against

197

* @returns Array of matching documents

198

*/

199

byExample(template: object): object[];

200

201

/**

202

* Find single object matching template

203

* @param template - Template object to match against

204

* @returns First matching document or null

205

*/

206

findObject(template: object): object | null;

207

208

/**

209

* Find multiple objects matching template

210

* @param template - Template object to match against

211

* @returns Array of matching documents

212

*/

213

findObjects(template: object): object[];

214

215

/**

216

* Find documents and update them in one operation

217

* @param filterObject - Query to find documents

218

* @param updateFunction - Function to update each document

219

* @returns Array of updated documents

220

*/

221

findAndUpdate(filterObject: object, updateFunction: (obj: object) => void): object[];

222

223

/**

224

* Find documents and remove them in one operation

225

* @param filterObject - Query to find documents

226

* @returns Array of removed documents

227

*/

228

findAndRemove(filterObject: object): object[];

229

230

/**

231

* Update documents matching filter function

232

* @param filterFunction - Function to identify documents to update

233

* @param updateFunction - Function to update each document

234

*/

235

updateWhere(filterFunction: (obj: object) => boolean, updateFunction: (obj: object) => void): void;

236

```

237

238

**Usage Examples:**

239

240

```javascript

241

// Find by example template

242

const users = users.byExample({ active: true, department: 'Engineering' });

243

244

// Find and update in one operation

245

const updated = users.findAndUpdate(

246

{ active: false },

247

(obj) => { obj.lastLogin = new Date(); }

248

);

249

250

// Find and remove inactive users

251

const removed = users.findAndRemove({ active: false });

252

253

// Update where function matches

254

users.updateWhere(

255

obj => obj.age > 65,

256

obj => { obj.retired = true; }

257

);

258

```

259

260

### Counting and Statistics

261

262

Count documents and calculate statistical values across the collection.

263

264

```javascript { .api }

265

/**

266

* Count documents in collection

267

* @param query - Optional query to filter documents

268

* @returns Number of matching documents

269

*/

270

count(query?: object): number;

271

272

/**

273

* Get maximum value of a field

274

* @param field - Field name to find maximum value

275

* @returns Maximum value

276

*/

277

max(field: string): any;

278

279

/**

280

* Get minimum value of a field

281

* @param field - Field name to find minimum value

282

* @returns Minimum value

283

*/

284

min(field: string): any;

285

286

/**

287

* Get record with maximum field value

288

* @param field - Field name to compare

289

* @returns Document with maximum field value

290

*/

291

maxRecord(field: string): object;

292

293

/**

294

* Get record with minimum field value

295

* @param field - Field name to compare

296

* @returns Document with minimum field value

297

*/

298

minRecord(field: string): object;

299

300

/**

301

* Calculate average of field values

302

* @param field - Field name to average

303

* @returns Average value

304

*/

305

avg(field: string): number;

306

307

/**

308

* Calculate standard deviation of field values

309

* @param field - Field name to calculate standard deviation

310

* @returns Standard deviation

311

*/

312

stdDev(field: string): number;

313

314

/**

315

* Find most frequent value in field

316

* @param field - Field name to analyze

317

* @returns Most frequent value

318

*/

319

mode(field: string): any;

320

321

/**

322

* Calculate median value of field

323

* @param field - Field name to calculate median

324

* @returns Median value

325

*/

326

median(field: string): number;

327

```

328

329

**Usage Examples:**

330

331

```javascript

332

// Count all users

333

const totalUsers = users.count();

334

335

// Count active users

336

const activeCount = users.count({ active: true });

337

338

// Statistical operations

339

const maxAge = users.max('age');

340

const minAge = users.min('age');

341

const avgAge = users.avg('age');

342

const oldestUser = users.maxRecord('age');

343

344

// Distribution analysis

345

const commonDepartment = users.mode('department');

346

const medianSalary = users.median('salary');

347

```

348

349

### Indexing Operations

350

351

Manage indexes for improved query performance.

352

353

```javascript { .api }

354

/**

355

* Ensure binary index exists on property

356

* @param property - Property name to index

357

* @param force - Force index rebuild

358

*/

359

ensureIndex(property: string, force?: boolean): void;

360

361

/**

362

* Ensure unique index exists on field

363

* @param field - Field name for unique index

364

*/

365

ensureUniqueIndex(field: string): void;

366

367

/**

368

* Ensure all configured indexes exist

369

* @param force - Force rebuild of all indexes

370

*/

371

ensureAllIndexes(force?: boolean): void;

372

373

/**

374

* Check and optionally rebuild specific index

375

* @param property - Property name to check

376

* @param options - Check options

377

*/

378

checkIndex(property: string, options?: object): void;

379

380

/**

381

* Check and optionally rebuild all indexes

382

* @param options - Check options

383

*/

384

checkAllIndexes(options?: object): void;

385

386

/**

387

* Get values from binary index

388

* @param property - Indexed property name

389

* @returns Array of indexed values

390

*/

391

getBinaryIndexValues(property: string): any[];

392

```

393

394

**Usage Examples:**

395

396

```javascript

397

// Create collection with indexes

398

const users = db.addCollection('users', {

399

unique: ['email'],

400

indices: ['age', 'department']

401

});

402

403

// Add index later

404

users.ensureIndex('lastName');

405

406

// Check if indexes need rebuilding

407

users.checkAllIndexes();

408

409

// Get indexed values

410

const departments = users.getBinaryIndexValues('department');

411

```

412

413

### Transform Operations

414

415

Manage named transform pipelines for reusable query operations.

416

417

```javascript { .api }

418

/**

419

* Add a named transform to the collection

420

* @param name - Transform name

421

* @param transform - Array of transform steps

422

*/

423

addTransform(name: string, transform: any[]): void;

424

425

/**

426

* Get a named transform by name

427

* @param name - Transform name

428

* @returns Transform array or null if not found

429

*/

430

getTransform(name: string): any[] | null;

431

432

/**

433

* Update an existing named transform

434

* @param name - Transform name

435

* @param transform - New transform steps

436

*/

437

setTransform(name: string, transform: any[]): void;

438

439

/**

440

* Remove a named transform

441

* @param name - Transform name

442

*/

443

removeTransform(name: string): void;

444

```

445

446

**Usage Examples:**

447

448

```javascript

449

// Define a reusable transform

450

users.addTransform('activeUsers', [

451

{ type: 'find', value: { active: true } },

452

{ type: 'simplesort', property: 'name' }

453

]);

454

455

// Use the transform

456

const result = users.chain('activeUsers').data();

457

458

// Update transform

459

users.setTransform('activeUsers', [

460

{ type: 'find', value: { active: true, verified: true } },

461

{ type: 'simplesort', property: 'name' }

462

]);

463

464

// Remove transform

465

users.removeTransform('activeUsers');

466

```

467

468

### Transaction Support

469

470

Transactional operations for consistent data modifications.

471

472

```javascript { .api }

473

/**

474

* Start a transaction on the collection

475

* @returns Collection instance for chaining

476

*/

477

startTransaction(): Collection;

478

479

/**

480

* Commit the current transaction

481

* @returns Collection instance for chaining

482

*/

483

commit(): Collection;

484

485

/**

486

* Rollback the current transaction

487

* @returns Collection instance for chaining

488

*/

489

rollback(): Collection;

490

```

491

492

**Usage Examples:**

493

494

```javascript

495

// Start transaction

496

users.startTransaction();

497

498

try {

499

// Perform multiple operations

500

users.insert({ name: 'Alice', age: 25 });

501

users.insert({ name: 'Bob', age: 30 });

502

503

// Update existing records

504

const activeUsers = users.find({ active: true });

505

activeUsers.forEach(user => {

506

user.lastUpdated = new Date();

507

users.update(user);

508

});

509

510

// Commit changes

511

users.commit();

512

console.log('Transaction committed successfully');

513

} catch (error) {

514

// Rollback on error

515

users.rollback();

516

console.error('Transaction rolled back:', error);

517

}

518

```

519

520

### TTL (Time To Live) Configuration

521

522

Configure automatic document expiration based on age.

523

524

```javascript { .api }

525

/**

526

* Set TTL (Time To Live) for documents in collection

527

* @param age - Maximum age in milliseconds

528

* @param interval - Check interval in milliseconds

529

*/

530

setTTL(age: number, interval?: number): void;

531

```

532

533

**Usage Examples:**

534

535

```javascript

536

// Set TTL when creating collection

537

const sessions = db.addCollection('sessions', {

538

ttl: 24 * 60 * 60 * 1000, // 24 hours

539

ttlInterval: 60 * 1000 // Check every minute

540

});

541

542

// Or set TTL later

543

sessions.setTTL(

544

30 * 60 * 1000, // 30 minutes

545

5 * 60 * 1000 // Check every 5 minutes

546

);

547

548

// Documents will be automatically removed when they exceed the age limit

549

```

550

551

### Auto-Update Observers

552

553

Manage automatic updates for live objects.

554

555

```javascript { .api }

556

/**

557

* Add auto-update observer for an object

558

* @param object - Object to observe for changes

559

*/

560

addAutoUpdateObserver(object: object): void;

561

562

/**

563

* Remove auto-update observer for an object

564

* @param object - Object to stop observing

565

*/

566

removeAutoUpdateObserver(object: object): void;

567

```

568

569

**Usage Examples:**

570

571

```javascript

572

// Enable auto-update for collection

573

const users = db.addCollection('users', {

574

autoupdate: true

575

});

576

577

// Insert document

578

const user = users.insert({ name: 'Alice', age: 25 });

579

580

// Modify the object directly - changes will be automatically saved

581

user.age = 26; // Collection automatically updated

582

583

// Manually manage observers

584

users.addAutoUpdateObserver(user);

585

users.removeAutoUpdateObserver(user);

586

```

587

588

### Staging Operations

589

590

Stage and commit changes in batches.

591

592

```javascript { .api }

593

/**

594

* Stage an object for later commit

595

* @param stageName - Name of the stage

596

* @param obj - Object to stage

597

*/

598

stage(stageName: string, obj: object): void;

599

600

/**

601

* Get staged objects by stage name

602

* @param name - Stage name

603

* @returns Array of staged objects

604

*/

605

getStage(name: string): object[];

606

607

/**

608

* Commit staged changes

609

* @param stageName - Name of stage to commit

610

* @param message - Optional commit message

611

*/

612

commitStage(stageName: string, message?: string): void;

613

```

614

615

**Usage Examples:**

616

617

```javascript

618

// Stage multiple changes

619

users.stage('batch1', { name: 'Alice', age: 25 });

620

users.stage('batch1', { name: 'Bob', age: 30 });

621

users.stage('batch1', { name: 'Charlie', age: 35 });

622

623

// Review staged changes

624

const staged = users.getStage('batch1');

625

console.log('Staged documents:', staged.length);

626

627

// Commit the stage

628

users.commitStage('batch1', 'Added new users batch');

629

```

630

631

### Advanced Operations

632

633

Specialized operations for complex data manipulation and analysis.

634

635

```javascript { .api }

636

/**

637

* Create a chainable resultset for complex operations

638

* @param transform - Transform name to apply

639

* @param parameters - Transform parameters

640

* @returns Resultset for chaining operations

641

*/

642

chain(transform?: string, parameters?: object): Resultset;

643

644

/**

645

* Extract unique values from a field

646

* @param field - Field name to extract values from

647

* @returns Array of unique values

648

*/

649

extract(field: string): any[];

650

651

/**

652

* Perform map-reduce operation on collection

653

* @param mapFunction - Map function to apply to each document

654

* @param reduceFunction - Reduce function to combine results

655

* @returns Reduced result

656

*/

657

mapReduce(mapFunction: (obj: object) => any, reduceFunction: (array: any[]) => any): any;

658

659

/**

660

* Perform equi-join with external data

661

* @param joinData - External data to join with

662

* @param leftJoinProp - Property from collection documents

663

* @param rightJoinProp - Property from external data

664

* @param mapFun - Optional function to transform join results

665

* @param dataOptions - Additional options

666

* @returns Array of joined results

667

*/

668

eqJoin(joinData: any[], leftJoinProp: string, rightJoinProp: string, mapFun?: Function, dataOptions?: object): object[];

669

```

670

671

**Usage Examples:**

672

673

```javascript

674

// Chain complex operations

675

const result = users.chain()

676

.find({ active: true })

677

.where(obj => obj.age > 25)

678

.simplesort('name')

679

.limit(10)

680

.data();

681

682

// Extract unique departments

683

const departments = users.extract('department');

684

685

// Map-reduce to calculate department sizes

686

const deptSizes = users.mapReduce(

687

obj => ({ [obj.department]: 1 }),

688

results => {

689

const counts = {};

690

results.forEach(result => {

691

Object.keys(result).forEach(dept => {

692

counts[dept] = (counts[dept] || 0) + result[dept];

693

});

694

});

695

return counts;

696

}

697

);

698

699

// Join with external data

700

const orders = [

701

{ userId: 1, total: 100 },

702

{ userId: 2, total: 200 }

703

];

704

const usersWithOrders = users.eqJoin(orders, 'id', 'userId');

705

```

706

707

### Async Operations

708

709

Perform asynchronous operations on collections.

710

711

```javascript { .api }

712

/**

713

* Execute function asynchronously on collection

714

* @param fun - Function to execute

715

* @param callback - Completion callback

716

*/

717

async(fun: Function, callback: Function): void;

718

```

719

720

**Usage Examples:**

721

722

```javascript

723

// Async operation example

724

users.async(

725

function(collection) {

726

// Perform heavy operation

727

return collection.find({ department: 'Engineering' })

728

.map(user => ({ ...user, processed: true }));

729

},

730

function(result) {

731

console.log('Async operation completed:', result.length);

732

}

733

);

734

```

735

736

### Internal Methods

737

738

Low-level methods for advanced usage and debugging.

739

740

```javascript { .api }

741

/**

742

* Ensure collection has sequential IDs without gaps

743

*/

744

ensureId(): void;

745

746

/**

747

* Asynchronous version of ensureId

748

* @param callback - Completion callback

749

*/

750

ensureIdAsync(callback: Function): void;

751

752

/**

753

* Configure collection options after creation

754

* @param options - Configuration options

755

*/

756

configureOptions(options: CollectionOptions): void;

757

758

/**

759

* Get binary index position for a data position

760

* @param dataPosition - Position in data array

761

* @param binaryIndexName - Name of binary index

762

* @returns Index position

763

*/

764

getBinaryIndexPosition(dataPosition: number, binaryIndexName: string): number;

765

766

/**

767

* Calculate range start for binary index searches

768

* @param prop - Property name

769

* @param val - Search value

770

* @param adaptive - Whether to use adaptive indices

771

* @param usingDotNotation - Whether using dot notation

772

* @returns Range start position

773

*/

774

calculateRangeStart(prop: string, val: any, adaptive?: boolean, usingDotNotation?: boolean): number;

775

776

/**

777

* Calculate range end for binary index searches

778

* @param prop - Property name

779

* @param val - Search value

780

* @param usingDotNotation - Whether using dot notation

781

* @returns Range end position

782

*/

783

calculateRangeEnd(prop: string, val: any, usingDotNotation?: boolean): number;

784

785

/**

786

* No-operation function for testing/debugging

787

*/

788

no_op(): void;

789

```

790

791

## Properties

792

793

```javascript { .api }

794

interface Collection {

795

/** Collection name */

796

name: string;

797

/** Array of documents */

798

data: object[];

799

/** Collection configuration options */

800

options: CollectionOptions;

801

/** Binary indices for optimized querying */

802

binaryIndices: { [field: string]: any };

803

/** Unique field constraints */

804

constraints: { unique: { [field: string]: any } };

805

/** Array of dynamic views */

806

DynamicViews: DynamicView[];

807

/** Transform functions */

808

transforms: { [name: string]: any[] };

809

/** Maximum $loki id assigned */

810

maxId: number;

811

/** Dirty flag indicating unsaved changes */

812

dirty: boolean;

813

}

814

```