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

advanced-querying.mddocs/

0

# Advanced Querying

1

2

Chainable query interface with filtering, sorting, transformations, and aggregation operations using the Resultset class for complex data operations.

3

4

## Capabilities

5

6

### Resultset Constructor

7

8

Creates a chainable query interface from a collection for complex operations.

9

10

```javascript { .api }

11

/**

12

* Creates a new resultset for chainable operations

13

* @param collection - Source collection

14

* @param options - Resultset options

15

*/

16

constructor Resultset(collection: Collection, options?: object);

17

```

18

19

**Usage Examples:**

20

21

```javascript

22

// Create resultset from collection

23

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

24

const resultset = new users.constructor.Resultset(users);

25

26

// Or create via collection.chain()

27

const resultset = users.chain();

28

```

29

30

### Query Operations

31

32

Filter documents using various query criteria and logical operations.

33

34

```javascript { .api }

35

/**

36

* Apply find query to filter documents

37

* @param query - MongoDB-style query object

38

* @param firstOnly - If true, stop after first match

39

* @returns Resultset for chaining

40

*/

41

find(query: object, firstOnly?: boolean): Resultset;

42

43

/**

44

* Apply OR query across multiple expressions

45

* @param expressionArray - Array of query expressions

46

* @returns Resultset for chaining

47

*/

48

findOr(expressionArray: object[]): Resultset;

49

50

/**

51

* Apply AND query across multiple expressions

52

* @param expressionArray - Array of query expressions

53

* @returns Resultset for chaining

54

*/

55

findAnd(expressionArray: object[]): Resultset;

56

57

/**

58

* Filter using custom function

59

* @param fun - Filter function returning boolean

60

* @returns Resultset for chaining

61

*/

62

where(fun: (obj: object) => boolean): Resultset;

63

```

64

65

**Usage Examples:**

66

67

```javascript

68

// Basic find operations

69

const activeUsers = users.chain()

70

.find({ active: true })

71

.data();

72

73

// OR query

74

const result = users.chain()

75

.findOr([

76

{ department: 'Engineering' },

77

{ department: 'Design' },

78

{ age: { $gt: 50 } }

79

])

80

.data();

81

82

// AND query

83

const result = users.chain()

84

.findAnd([

85

{ active: true },

86

{ age: { $gte: 25 } },

87

{ department: { $ne: 'Intern' } }

88

])

89

.data();

90

91

// Custom filter function

92

const result = users.chain()

93

.where(obj => obj.email.includes('@company.com'))

94

.data();

95

```

96

97

### Sorting Operations

98

99

Sort resultset data using various criteria and custom comparison functions.

100

101

```javascript { .api }

102

/**

103

* Sort using custom comparison function

104

* @param comparefun - Function returning -1, 0, or 1 for comparison

105

* @returns Resultset for chaining

106

*/

107

sort(comparefun: (a: object, b: object) => number): Resultset;

108

109

/**

110

* Simple sort by property name

111

* @param propname - Property name to sort by

112

* @param options - Sort options (desc: boolean)

113

* @returns Resultset for chaining

114

*/

115

simplesort(propname: string, options?: { desc?: boolean }): Resultset;

116

117

/**

118

* Sort by multiple properties with individual sort directions

119

* @param properties - Array of [property, isDescending] pairs

120

* @returns Resultset for chaining

121

*/

122

compoundsort(properties: [string, boolean][]): Resultset;

123

```

124

125

**Usage Examples:**

126

127

```javascript

128

// Simple ascending sort

129

const result = users.chain()

130

.find({ active: true })

131

.simplesort('name')

132

.data();

133

134

// Simple descending sort

135

const result = users.chain()

136

.find({ active: true })

137

.simplesort('age', { desc: true })

138

.data();

139

140

// Compound sort

141

const result = users.chain()

142

.find({ active: true })

143

.compoundsort([

144

['department', false], // ascending

145

['age', true] // descending

146

])

147

.data();

148

149

// Custom sort function

150

const result = users.chain()

151

.find({ active: true })

152

.sort((a, b) => {

153

// Sort by name length, then alphabetically

154

if (a.name.length !== b.name.length) {

155

return a.name.length - b.name.length;

156

}

157

return a.name.localeCompare(b.name);

158

})

159

.data();

160

```

161

162

### Pagination Operations

163

164

Limit and offset results for pagination and data chunking.

165

166

```javascript { .api }

167

/**

168

* Limit number of results returned

169

* @param qty - Maximum number of results

170

* @returns Resultset for chaining

171

*/

172

limit(qty: number): Resultset;

173

174

/**

175

* Skip specified number of results

176

* @param pos - Number of results to skip

177

* @returns Resultset for chaining

178

*/

179

offset(pos: number): Resultset;

180

```

181

182

**Usage Examples:**

183

184

```javascript

185

// Get first 10 users

186

const firstPage = users.chain()

187

.find({ active: true })

188

.limit(10)

189

.data();

190

191

// Get users 11-20 (second page)

192

const secondPage = users.chain()

193

.find({ active: true })

194

.offset(10)

195

.limit(10)

196

.data();

197

198

// Get top 5 highest paid employees

199

const topEarners = users.chain()

200

.find({ active: true })

201

.simplesort('salary', { desc: true })

202

.limit(5)

203

.data();

204

```

205

206

### Data Retrieval

207

208

Retrieve the final results from the query chain.

209

210

```javascript { .api }

211

/**

212

* Execute the query chain and return results

213

* @param options - Data retrieval options

214

* @returns Array of documents matching the query chain

215

*/

216

data(options?: { removeMeta?: boolean, forceClones?: boolean }): object[];

217

218

/**

219

* Get count of documents in resultset without retrieving data

220

* @returns Number of documents that would be returned

221

*/

222

count(): number;

223

```

224

225

**Usage Examples:**

226

227

```javascript

228

// Get results with metadata

229

const results = users.chain()

230

.find({ active: true })

231

.simplesort('name')

232

.data();

233

234

// Get results without metadata

235

const cleanResults = users.chain()

236

.find({ active: true })

237

.data({ removeMeta: true });

238

239

// Just get the count

240

const activeCount = users.chain()

241

.find({ active: true })

242

.count();

243

```

244

245

### Transformation Operations

246

247

Apply transformations and modifications to query results.

248

249

```javascript { .api }

250

/**

251

* Apply a transform to the resultset

252

* @param transform - Transform name or function

253

* @param parameters - Transform parameters

254

* @returns Resultset for chaining

255

*/

256

transform(transform: string | Function, parameters?: object): Resultset;

257

258

/**

259

* Update documents in the resultset

260

* @param updateFunction - Function to update each document

261

* @returns Resultset for chaining

262

*/

263

update(updateFunction: (obj: object) => void): object[];

264

265

/**

266

* Remove documents in the resultset from the collection

267

* @returns Array of removed documents

268

*/

269

remove(): object[];

270

271

/**

272

* Copy the resultset

273

* @returns New resultset with same filters

274

*/

275

copy(): Resultset;

276

277

/**

278

* Reset resultset to include all documents

279

* @returns Resultset for chaining

280

*/

281

reset(): Resultset;

282

283

/**

284

* Create a branch (copy) of the resultset

285

* @returns New resultset with same filters

286

*/

287

branch(): Resultset;

288

289

/**

290

* Serialize resultset to JSON

291

* @returns JSON representation of the resultset

292

*/

293

toJSON(): string;

294

```

295

296

**Usage Examples:**

297

298

```javascript

299

// Apply transform

300

const transformed = users.chain()

301

.find({ active: true })

302

.transform('extractName') // Assuming transform exists

303

.data();

304

305

// Update documents in resultset

306

const updated = users.chain()

307

.find({ department: 'Engineering' })

308

.update(obj => {

309

obj.lastReviewDate = new Date();

310

obj.needsReview = false;

311

});

312

313

// Remove documents matching criteria

314

const removed = users.chain()

315

.find({ active: false, lastLogin: { $lt: new Date('2020-01-01') } })

316

.remove();

317

318

// Copy resultset for different operations

319

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

320

const engineers = baseQuery.copy().find({ department: 'Engineering' }).data();

321

const designers = baseQuery.copy().find({ department: 'Design' }).data();

322

```

323

324

### Aggregation Operations

325

326

Perform aggregation and join operations on query results.

327

328

```javascript { .api }

329

/**

330

* Perform map-reduce operation on resultset

331

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

332

* @param reduceFunction - Reduce function to combine results

333

* @returns Reduced result

334

*/

335

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

336

337

/**

338

* Perform equi-join with external data

339

* @param joinData - External data to join with

340

* @param leftJoinKey - Property from resultset documents

341

* @param rightJoinKey - Property from external data

342

* @param mapFun - Optional function to transform join results

343

* @param dataOptions - Additional options

344

* @returns Array of joined results

345

*/

346

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

347

348

/**

349

* Apply map operation to transform each document

350

* @param mapFun - Map function to apply

351

* @param dataOptions - Additional options

352

* @returns Array of transformed results

353

*/

354

map(mapFun: (obj: object) => any, dataOptions?: object): any[];

355

```

356

357

**Usage Examples:**

358

359

```javascript

360

// Map-reduce to calculate department statistics

361

const deptStats = users.chain()

362

.find({ active: true })

363

.mapReduce(

364

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

365

results => {

366

const stats = {};

367

results.forEach(result => {

368

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

369

if (!stats[dept]) {

370

stats[dept] = { count: 0, totalSalary: 0 };

371

}

372

stats[dept].count += result[dept].count;

373

stats[dept].totalSalary += result[dept].totalSalary;

374

});

375

});

376

// Calculate averages

377

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

378

stats[dept].avgSalary = stats[dept].totalSalary / stats[dept].count;

379

});

380

return stats;

381

}

382

);

383

384

// Join with external orders data

385

const orders = [

386

{ customerId: 1, total: 150.00, date: '2023-01-15' },

387

{ customerId: 2, total: 75.50, date: '2023-01-16' }

388

];

389

390

const usersWithOrders = users.chain()

391

.find({ active: true })

392

.eqJoin(orders, 'id', 'customerId', (left, right) => ({

393

user: left,

394

orderTotal: right.total,

395

orderDate: right.date

396

}));

397

398

// Map to extract specific fields

399

const userSummaries = users.chain()

400

.find({ active: true })

401

.map(obj => ({

402

name: obj.name,

403

email: obj.email,

404

department: obj.department

405

}));

406

```

407

408

## Query Operators

409

410

LokiJS supports MongoDB-style query operators for complex filtering:

411

412

```javascript { .api }

413

// Comparison operators

414

$eq: any; // Strict equality

415

$aeq: any; // Abstract equality (==)

416

$ne: any; // Not equal

417

$gt: any; // Greater than

418

$gte: any; // Greater than or equal

419

$lt: any; // Less than

420

$lte: any; // Less than or equal

421

422

// Array operators

423

$in: any[]; // Value in array

424

$nin: any[]; // Value not in array

425

$contains: any; // Array contains value

426

$containsAny: any[]; // Array contains any of values

427

$containsNone: any[]; // Array contains none of values

428

429

// Object operators

430

$exists: boolean; // Property exists

431

$type: string; // Type checking ('string', 'number', etc.)

432

$size: number; // Array/object size

433

$regex: RegExp; // Regular expression match

434

435

// Logical operators

436

$and: object[]; // Logical AND

437

$or: object[]; // Logical OR

438

$not: object; // Logical NOT

439

440

// Numeric operators

441

$between: [any, any]; // Between two values

442

$finite: boolean; // Is finite number

443

444

// Advanced operators

445

$dteq: any; // Date/abstract equality

446

$jgt: any; // JavaScript greater than (lightweight)

447

$jgte: any; // JavaScript greater than or equal

448

$jlt: any; // JavaScript less than (lightweight)

449

$jlte: any; // JavaScript less than or equal

450

$jbetween: [any, any]; // JavaScript between (lightweight)

451

$inSet: Set<any>; // Value in Set object

452

$keyin: object; // Property key exists in object

453

$nkeyin: object; // Property key does not exist in object

454

$definedin: object; // Property is defined in object (not undefined)

455

$undefinedin: object; // Property is undefined in object

456

$containsString: string; // String contains substring

457

$elemMatch: object; // Array element matches query

458

459

// Custom operators

460

$where: Function; // Custom function filter

461

```

462

463

**Usage Examples:**

464

465

```javascript

466

// Comparison operators

467

const adults = users.chain().find({ age: { $gte: 18 } }).data();

468

const active = users.chain().find({ status: { $ne: 'inactive' } }).data();

469

470

// Array operators

471

const managers = users.chain().find({

472

roles: { $contains: 'manager' }

473

}).data();

474

475

const techRoles = users.chain().find({

476

skills: { $containsAny: ['JavaScript', 'Python', 'Java'] }

477

}).data();

478

479

// Object operators

480

const hasPhone = users.chain().find({

481

phone: { $exists: true }

482

}).data();

483

484

const numbers = users.chain().find({

485

employeeId: { $type: 'number' }

486

}).data();

487

488

// Logical operators

489

const seniorEngineers = users.chain().find({

490

$and: [

491

{ department: 'Engineering' },

492

{ experience: { $gte: 5 } },

493

{ level: { $in: ['Senior', 'Lead', 'Principal'] } }

494

]

495

}).data();

496

497

// Custom function filter

498

const recentHires = users.chain().find({

499

$where: function(obj) {

500

const hireDate = new Date(obj.hireDate);

501

const sixMonthsAgo = new Date();

502

sixMonthsAgo.setMonth(sixMonthsAgo.getMonth() - 6);

503

return hireDate > sixMonthsAgo;

504

}

505

}).data();

506

507

// Advanced operators

508

const advancedUsers = users.chain().find({

509

// Date equality

510

createdAt: { $dteq: new Date('2023-01-01') },

511

512

// Lightweight JavaScript comparisons

513

score: { $jgt: 85 },

514

515

// Between range (lightweight)

516

age: { $jbetween: [25, 65] },

517

518

// Set membership

519

department: { $inSet: new Set(['Engineering', 'Design']) },

520

521

// Object property checks

522

userId: { $keyin: userMap },

523

preferences: { $definedin: { theme: 'dark' } },

524

525

// String operations

526

email: { $containsString: '@company.com' },

527

528

// Array element matching

529

orders: {

530

$elemMatch: {

531

status: 'completed',

532

total: { $gt: 100 }

533

}

534

}

535

}).data();

536

```

537

538

### Additional Query Examples

539

540

Advanced query patterns using the extended operator set.

541

542

```javascript

543

// Complex nested queries

544

const complexResults = users.chain()

545

.find({

546

$and: [

547

{ status: 'active' },

548

{

549

$or: [

550

{ department: { $inSet: new Set(['Engineering', 'Design']) } },

551

{ skills: { $containsAny: ['leadership', 'management'] } }

552

]

553

},

554

{

555

projects: {

556

$elemMatch: {

557

status: 'completed',

558

budget: { $jbetween: [10000, 100000] },

559

deadline: { $dteq: new Date('2023-12-31') }

560

}

561

}

562

}

563

]

564

})

565

.data();

566

567

// String and object operations

568

const textSearchResults = users.chain()

569

.find({

570

// String contains

571

biography: { $containsString: 'engineer' },

572

573

// Property existence

574

permissions: { $definedin: { admin: true } },

575

576

// Key membership

577

userId: { $keyin: { 1: true, 2: true, 3: true } },

578

579

// Undefined check

580

deletedAt: { $undefinedin: {} }

581

})

582

.data();

583

```

584

585

### Resultset Aliases

586

587

Alternative method names for MongoDB compatibility.

588

589

```javascript { .api }

590

// Logical operator aliases

591

$or(expressionArray: object[]): Resultset; // Alias for findOr

592

$and(expressionArray: object[]): Resultset; // Alias for findAnd

593

```

594

595

**Usage Examples:**

596

597

```javascript

598

// Use MongoDB-style operator aliases

599

const result1 = users.chain()

600

.$or([

601

{ department: 'Engineering' },

602

{ department: 'Design' }

603

])

604

.data();

605

606

const result2 = users.chain()

607

.$and([

608

{ active: true },

609

{ age: { $gte: 25 } }

610

])

611

.data();

612

```

613

614

## Properties

615

616

```javascript { .api }

617

interface Resultset {

618

/** Reference to source collection */

619

collection: Collection;

620

/** Array of filtered row indices */

621

filteredrows: number[];

622

/** Filter initialization flag */

623

filterInitialized: boolean;

624

}

625

```