or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

bloom-filters.mdclient-management.mdindex.mdjson-operations.mdredis-commands.mdsearch-indexing.mdtime-series.md

bloom-filters.mddocs/

0

# Bloom Filters

1

2

Probabilistic data structures including Bloom filters, Count-Min Sketch, Cuckoo filters, T-Digest, and Top-K using RedisBloom. These structures provide memory-efficient approximations for set membership, counting, ranking, and statistical operations.

3

4

## Capabilities

5

6

### Bloom Filters

7

8

Probabilistic set membership testing with configurable false positive rates.

9

10

```typescript { .api }

11

/**

12

* Add item to Bloom filter

13

* @param key - Bloom filter key

14

* @param item - Item to add

15

* @returns 1 if item was added, 0 if probably already exists

16

*/

17

function add(key: RedisArgument, item: RedisArgument): Promise<BooleanReply>;

18

19

/**

20

* Add multiple items to Bloom filter

21

* @param key - Bloom filter key

22

* @param items - Items to add

23

* @returns Array of results for each item

24

*/

25

function mAdd(key: RedisArgument, ...items: RedisArgument[]): Promise<ArrayReply<BooleanReply>>;

26

27

/**

28

* Check if item exists in Bloom filter

29

* @param key - Bloom filter key

30

* @param item - Item to check

31

* @returns 1 if item probably exists, 0 if definitely does not exist

32

*/

33

function exists(key: RedisArgument, item: RedisArgument): Promise<BooleanReply>;

34

35

/**

36

* Check multiple items in Bloom filter

37

* @param key - Bloom filter key

38

* @param items - Items to check

39

* @returns Array of existence results for each item

40

*/

41

function mExists(key: RedisArgument, ...items: RedisArgument[]): Promise<ArrayReply<BooleanReply>>;

42

43

/**

44

* Reserve Bloom filter with specific parameters

45

* @param key - Bloom filter key

46

* @param errorRate - Desired false positive rate (0 < errorRate < 1)

47

* @param capacity - Expected number of items

48

* @param options - Optional configuration

49

* @returns 'OK'

50

*/

51

function reserve(

52

key: RedisArgument,

53

errorRate: number,

54

capacity: number,

55

options?: BfReserveOptions

56

): Promise<SimpleStringReply<'OK'>>;

57

58

/**

59

* Get Bloom filter information and statistics

60

* @param key - Bloom filter key

61

* @returns Array containing filter info

62

*/

63

function info(key: RedisArgument): Promise<ArrayReply>;

64

65

/**

66

* Get cardinality estimation of Bloom filter

67

* @param key - Bloom filter key

68

* @returns Estimated number of unique items added

69

*/

70

function card(key: RedisArgument): Promise<NumberReply>;

71

72

/**

73

* Insert items with options

74

* @param key - Bloom filter key

75

* @param options - Insert configuration

76

* @param items - Items to insert

77

* @returns Array of results for each item

78

*/

79

function insert(

80

key: RedisArgument,

81

options: BfInsertOptions,

82

...items: RedisArgument[]

83

): Promise<ArrayReply<BooleanReply>>;

84

85

/**

86

* Begin incremental save of Bloom filter

87

* @param key - Bloom filter key

88

* @param iterator - Iterator value (start at 0)

89

* @returns Object with iterator and chunk data

90

*/

91

function scanDump(key: RedisArgument, iterator: number): Promise<{ iterator: NumberReply; chunk: BlobStringReply }>;

92

93

/**

94

* Restore Bloom filter chunk

95

* @param key - Bloom filter key

96

* @param iterator - Iterator value from scanDump

97

* @param chunk - Data chunk from scanDump

98

* @returns 'OK'

99

*/

100

function loadChunk(key: RedisArgument, iterator: number, chunk: RedisArgument): Promise<SimpleStringReply<'OK'>>;

101

102

interface BfReserveOptions {

103

/** Number of sub-filters for expansion */

104

EXPANSION?: number;

105

/** Non-scaling filter (no expansion) */

106

NONSCALING?: boolean;

107

}

108

109

interface BfInsertOptions {

110

/** Capacity for auto-created filter */

111

CAPACITY?: number;

112

/** Error rate for auto-created filter */

113

ERROR?: number;

114

/** Expansion rate for auto-created filter */

115

EXPANSION?: number;

116

/** Create non-scaling filter */

117

NONSCALING?: boolean;

118

/** Only insert if key doesn't exist */

119

NOCREATE?: boolean;

120

}

121

```

122

123

**Usage Examples:**

124

125

```typescript

126

import { createClient } from "redis";

127

128

const client = createClient();

129

await client.connect();

130

131

// Reserve Bloom filter with specific parameters

132

await client.bf.reserve("user_emails", 0.01, 10000); // 1% false positive rate, 10k capacity

133

134

// Add items to filter

135

await client.bf.add("user_emails", "alice@example.com");

136

await client.bf.add("user_emails", "bob@example.com");

137

138

// Add multiple items at once

139

const addResults = await client.bf.mAdd("user_emails",

140

"charlie@example.com",

141

"diana@example.com",

142

"alice@example.com" // Already exists

143

);

144

// Results: [1, 1, 0] (1=added, 0=probably already exists)

145

146

// Check membership

147

const exists1 = await client.bf.exists("user_emails", "alice@example.com"); // 1 (probably exists)

148

const exists2 = await client.bf.exists("user_emails", "unknown@example.com"); // 0 (definitely not)

149

150

// Check multiple items

151

const existsResults = await client.bf.mExists("user_emails",

152

"alice@example.com", // Exists

153

"bob@example.com", // Exists

154

"unknown@example.com" // Doesn't exist

155

);

156

// Results: [1, 1, 0]

157

158

// Get filter statistics

159

const info = await client.bf.info("user_emails");

160

console.log("Filter info:", info);

161

162

// Get cardinality estimate

163

const cardinality = await client.bf.card("user_emails");

164

console.log("Estimated items:", cardinality);

165

166

// Insert with auto-creation

167

await client.bf.insert("auto_filter", {

168

CAPACITY: 5000,

169

ERROR: 0.001 // 0.1% false positive rate

170

}, "item1", "item2", "item3");

171

```

172

173

### Count-Min Sketch

174

175

Frequency estimation for streaming data with bounded error guarantees.

176

177

```typescript { .api }

178

/**

179

* Initialize Count-Min Sketch by dimensions

180

* @param key - Sketch key

181

* @param width - Width parameter (affects accuracy)

182

* @param depth - Depth parameter (affects accuracy)

183

* @returns 'OK'

184

*/

185

function initByDim(key: RedisArgument, width: number, depth: number): Promise<SimpleStringReply<'OK'>>;

186

187

/**

188

* Initialize Count-Min Sketch by error and probability parameters

189

* @param key - Sketch key

190

* @param error - Relative error (0 < error < 1)

191

* @param probability - Probability of error (0 < probability < 1)

192

* @returns 'OK'

193

*/

194

function initByProb(key: RedisArgument, error: number, probability: number): Promise<SimpleStringReply<'OK'>>;

195

196

/**

197

* Increment items in Count-Min Sketch

198

* @param key - Sketch key

199

* @param items - Array of item-increment pairs

200

* @returns Array of estimated frequencies after increment

201

*/

202

function incrBy(key: RedisArgument, ...items: Array<{ item: RedisArgument; increment: number }>): Promise<ArrayReply<NumberReply>>;

203

204

/**

205

* Query estimated frequencies of items

206

* @param key - Sketch key

207

* @param items - Items to query

208

* @returns Array of estimated frequencies

209

*/

210

function query(key: RedisArgument, ...items: RedisArgument[]): Promise<ArrayReply<NumberReply>>;

211

212

/**

213

* Merge multiple sketches into destination

214

* @param destKey - Destination sketch key

215

* @param srcKeys - Source sketch keys to merge

216

* @param weights - Optional weights for each source sketch

217

* @returns 'OK'

218

*/

219

function merge(destKey: RedisArgument, srcKeys: RedisArgument[], weights?: number[]): Promise<SimpleStringReply<'OK'>>;

220

221

/**

222

* Get Count-Min Sketch information

223

* @param key - Sketch key

224

* @returns Array containing sketch info

225

*/

226

function info(key: RedisArgument): Promise<ArrayReply>;

227

```

228

229

**Usage Examples:**

230

231

```typescript

232

// Initialize sketch with specific dimensions

233

await client.cms.initByDim("page_views", 2000, 5); // 2000 width, 5 depth

234

235

// Initialize sketch with error/probability bounds

236

await client.cms.initByProb("word_count", 0.001, 0.01); // 0.1% error, 1% probability

237

238

// Increment item frequencies

239

const frequencies = await client.cms.incrBy("page_views",

240

{ item: "/home", increment: 10 },

241

{ item: "/about", increment: 5 },

242

{ item: "/contact", increment: 2 }

243

);

244

console.log("New frequencies:", frequencies); // [10, 5, 2]

245

246

// Add more visits

247

await client.cms.incrBy("page_views",

248

{ item: "/home", increment: 15 },

249

{ item: "/products", increment: 8 }

250

);

251

252

// Query frequencies

253

const counts = await client.cms.query("page_views", "/home", "/about", "/products", "/unknown");

254

console.log("Estimated counts:", counts); // [25, 5, 8, 0] (approximately)

255

256

// Create another sketch for merging

257

await client.cms.initByDim("page_views_backup", 2000, 5);

258

await client.cms.incrBy("page_views_backup",

259

{ item: "/home", increment: 5 },

260

{ item: "/blog", increment: 12 }

261

);

262

263

// Merge sketches

264

await client.cms.merge("page_views_combined", ["page_views", "page_views_backup"]);

265

266

// Query merged results

267

const mergedCounts = await client.cms.query("page_views_combined", "/home", "/blog");

268

console.log("Merged counts:", mergedCounts); // [30, 12] (approximately)

269

270

// Get sketch info

271

const info = await client.cms.info("page_views");

272

console.log("Sketch info:", info);

273

```

274

275

### Cuckoo Filters

276

277

Alternative to Bloom filters with deletion support and generally better performance.

278

279

```typescript { .api }

280

/**

281

* Reserve Cuckoo filter with specific capacity

282

* @param key - Filter key

283

* @param capacity - Maximum number of items

284

* @param options - Optional configuration

285

* @returns 'OK'

286

*/

287

function reserve(key: RedisArgument, capacity: number, options?: CfReserveOptions): Promise<SimpleStringReply<'OK'>>;

288

289

/**

290

* Add item to Cuckoo filter

291

* @param key - Filter key

292

* @param item - Item to add

293

* @returns 1 if added successfully

294

*/

295

function add(key: RedisArgument, item: RedisArgument): Promise<BooleanReply>;

296

297

/**

298

* Add item only if it doesn't exist

299

* @param key - Filter key

300

* @param item - Item to add

301

* @returns 1 if added, 0 if already exists

302

*/

303

function addNx(key: RedisArgument, item: RedisArgument): Promise<BooleanReply>;

304

305

/**

306

* Insert items with auto-creation

307

* @param key - Filter key

308

* @param options - Insert configuration

309

* @param items - Items to insert

310

* @returns Array of results for each item

311

*/

312

function insert(key: RedisArgument, options: CfInsertOptions, ...items: RedisArgument[]): Promise<ArrayReply<BooleanReply>>;

313

314

/**

315

* Check if item exists in Cuckoo filter

316

* @param key - Filter key

317

* @param item - Item to check

318

* @returns 1 if exists, 0 if not

319

*/

320

function exists(key: RedisArgument, item: RedisArgument): Promise<BooleanReply>;

321

322

/**

323

* Delete item from Cuckoo filter

324

* @param key - Filter key

325

* @param item - Item to delete

326

* @returns 1 if deleted, 0 if not found

327

*/

328

function del(key: RedisArgument, item: RedisArgument): Promise<BooleanReply>;

329

330

/**

331

* Count occurrences of item in filter

332

* @param key - Filter key

333

* @param item - Item to count

334

* @returns Number of occurrences (0-2 typically)

335

*/

336

function count(key: RedisArgument, item: RedisArgument): Promise<NumberReply>;

337

338

/**

339

* Get Cuckoo filter information

340

* @param key - Filter key

341

* @returns Array containing filter info

342

*/

343

function info(key: RedisArgument): Promise<ArrayReply>;

344

345

interface CfReserveOptions {

346

/** Bucket size (default: 2) */

347

BUCKETSIZE?: number;

348

/** Maximum number of iterations for insertion */

349

MAXITERATIONS?: number;

350

/** Expansion rate when filter is full */

351

EXPANSION?: number;

352

}

353

354

interface CfInsertOptions {

355

/** Capacity for auto-created filter */

356

CAPACITY?: number;

357

/** Only insert if key doesn't exist */

358

NOCREATE?: boolean;

359

}

360

```

361

362

**Usage Examples:**

363

364

```typescript

365

// Reserve Cuckoo filter

366

await client.cf.reserve("user_sessions", 10000, {

367

BUCKETSIZE: 4,

368

MAXITERATIONS: 20,

369

EXPANSION: 1

370

});

371

372

// Add items

373

await client.cf.add("user_sessions", "session_123");

374

await client.cf.add("user_sessions", "session_456");

375

376

// Add only if not exists

377

const added = await client.cf.addNx("user_sessions", "session_123"); // 0 (already exists)

378

const newAdded = await client.cf.addNx("user_sessions", "session_789"); // 1 (new)

379

380

// Check existence

381

const exists = await client.cf.exists("user_sessions", "session_123"); // 1

382

const notExists = await client.cf.exists("user_sessions", "session_999"); // 0

383

384

// Count occurrences

385

const count = await client.cf.count("user_sessions", "session_123"); // 1

386

387

// Delete item (unlike Bloom filters!)

388

const deleted = await client.cf.del("user_sessions", "session_123"); // 1

389

const checkDeleted = await client.cf.exists("user_sessions", "session_123"); // 0

390

391

// Insert with auto-creation

392

await client.cf.insert("temp_filter", {

393

CAPACITY: 1000

394

}, "item1", "item2", "item3");

395

396

// Get filter info

397

const info = await client.cf.info("user_sessions");

398

console.log("Filter info:", info);

399

```

400

401

### T-Digest

402

403

Probabilistic data structure for estimating quantiles and percentiles of streaming data.

404

405

```typescript { .api }

406

/**

407

* Create T-Digest with optional compression parameter

408

* @param key - T-Digest key

409

* @param compression - Compression factor (default: 100, higher = more accurate)

410

* @returns 'OK'

411

*/

412

function create(key: RedisArgument, compression?: number): Promise<SimpleStringReply<'OK'>>;

413

414

/**

415

* Reset T-Digest to empty state

416

* @param key - T-Digest key

417

* @returns 'OK'

418

*/

419

function reset(key: RedisArgument): Promise<SimpleStringReply<'OK'>>;

420

421

/**

422

* Add values to T-Digest

423

* @param key - T-Digest key

424

* @param values - Numeric values to add

425

* @returns 'OK'

426

*/

427

function add(key: RedisArgument, ...values: number[]): Promise<SimpleStringReply<'OK'>>;

428

429

/**

430

* Merge multiple T-Digests

431

* @param destKey - Destination key

432

* @param srcKeys - Source T-Digest keys

433

* @param options - Optional compression and weights

434

* @returns 'OK'

435

*/

436

function merge(destKey: RedisArgument, srcKeys: RedisArgument[], options?: TDigestMergeOptions): Promise<SimpleStringReply<'OK'>>;

437

438

/**

439

* Get minimum value

440

* @param key - T-Digest key

441

* @returns Minimum value

442

*/

443

function min(key: RedisArgument): Promise<DoubleReply>;

444

445

/**

446

* Get maximum value

447

* @param key - T-Digest key

448

* @returns Maximum value

449

*/

450

function max(key: RedisArgument): Promise<DoubleReply>;

451

452

/**

453

* Get quantile values

454

* @param key - T-Digest key

455

* @param quantiles - Quantile values (0.0 to 1.0)

456

* @returns Array of quantile values

457

*/

458

function quantile(key: RedisArgument, ...quantiles: number[]): Promise<ArrayReply<DoubleReply>>;

459

460

/**

461

* Get cumulative distribution function values

462

* @param key - T-Digest key

463

* @param values - Values to get CDF for

464

* @returns Array of CDF values (0.0 to 1.0)

465

*/

466

function cdf(key: RedisArgument, ...values: number[]): Promise<ArrayReply<DoubleReply>>;

467

468

/**

469

* Get T-Digest information

470

* @param key - T-Digest key

471

* @returns Array containing digest info

472

*/

473

function info(key: RedisArgument): Promise<ArrayReply>;

474

475

interface TDigestMergeOptions {

476

/** Compression factor for merged digest */

477

COMPRESSION?: number;

478

/** Override destination key */

479

OVERRIDE?: boolean;

480

}

481

```

482

483

**Usage Examples:**

484

485

```typescript

486

// Create T-Digest for response time analysis

487

await client.tDigest.create("response_times", 200); // Higher compression for accuracy

488

489

// Add response time measurements (in milliseconds)

490

await client.tDigest.add("response_times",

491

45, 52, 38, 67, 91, 23, 156, 78, 44, 89,

492

234, 67, 45, 123, 78, 56, 234, 67, 89, 145

493

);

494

495

// Add more measurements over time

496

await client.tDigest.add("response_times", 67, 89, 234, 45, 78, 123, 56);

497

498

// Get basic statistics

499

const minTime = await client.tDigest.min("response_times");

500

const maxTime = await client.tDigest.max("response_times");

501

console.log(`Response time range: ${minTime}ms - ${maxTime}ms`);

502

503

// Get percentiles (common SLA metrics)

504

const percentiles = await client.tDigest.quantile("response_times",

505

0.5, // 50th percentile (median)

506

0.9, // 90th percentile

507

0.95, // 95th percentile

508

0.99 // 99th percentile

509

);

510

console.log("Percentiles (50%, 90%, 95%, 99%):", percentiles);

511

512

// Get probability of response time being under certain thresholds

513

const cdfValues = await client.tDigest.cdf("response_times", 100, 200, 500);

514

console.log("Probability under 100ms, 200ms, 500ms:", cdfValues);

515

516

// Create another digest for different service

517

await client.tDigest.create("service_b_times", 100);

518

await client.tDigest.add("service_b_times", 123, 145, 167, 189, 234, 67, 89);

519

520

// Merge digests for overall analysis

521

await client.tDigest.merge("combined_times", ["response_times", "service_b_times"], {

522

COMPRESSION: 200

523

});

524

525

// Analyze combined data

526

const combinedP95 = await client.tDigest.quantile("combined_times", 0.95);

527

console.log("Combined 95th percentile:", combinedP95);

528

529

// Get digest info

530

const info = await client.tDigest.info("response_times");

531

console.log("T-Digest info:", info);

532

```

533

534

### Top-K

535

536

Track top-K most frequent items in a stream with bounded memory usage.

537

538

```typescript { .api }

539

/**

540

* Reserve Top-K filter with capacity and optional parameters

541

* @param key - Top-K key

542

* @param k - Number of top items to track

543

* @param width - Width parameter (affects accuracy)

544

* @param depth - Depth parameter (affects accuracy)

545

* @param decay - Decay factor for aging (0.0 to 1.0)

546

* @returns 'OK'

547

*/

548

function reserve(key: RedisArgument, k: number, width?: number, depth?: number, decay?: number): Promise<SimpleStringReply<'OK'>>;

549

550

/**

551

* Add items to Top-K

552

* @param key - Top-K key

553

* @param items - Items to add

554

* @returns Array of items that were expelled from top-K (null if no expulsion)

555

*/

556

function add(key: RedisArgument, ...items: RedisArgument[]): Promise<ArrayReply<BlobStringReply | null>>;

557

558

/**

559

* Increment items by specific amounts

560

* @param key - Top-K key

561

* @param itemIncrements - Array of item-increment pairs

562

* @returns Array of items that were expelled from top-K

563

*/

564

function incrBy(key: RedisArgument, ...itemIncrements: Array<{ item: RedisArgument; increment: number }>): Promise<ArrayReply<BlobStringReply | null>>;

565

566

/**

567

* Query if items are in current top-K

568

* @param key - Top-K key

569

* @param items - Items to query

570

* @returns Array of boolean results for each item

571

*/

572

function query(key: RedisArgument, ...items: RedisArgument[]): Promise<ArrayReply<BooleanReply>>;

573

574

/**

575

* Get current top-K list

576

* @param key - Top-K key

577

* @returns Array of current top-K items

578

*/

579

function list(key: RedisArgument): Promise<ArrayReply<BlobStringReply>>;

580

581

/**

582

* Get current top-K list with counts

583

* @param key - Top-K key

584

* @returns Array alternating between items and their counts

585

*/

586

function listWithCount(key: RedisArgument): Promise<ArrayReply<BlobStringReply | NumberReply>>;

587

588

/**

589

* Get Top-K information

590

* @param key - Top-K key

591

* @returns Array containing filter info

592

*/

593

function info(key: RedisArgument): Promise<ArrayReply>;

594

```

595

596

**Usage Examples:**

597

598

```typescript

599

// Reserve Top-K for tracking most popular products

600

await client.topK.reserve("popular_products", 10, 50, 7, 0.9); // Track top 10 items

601

602

// Add product views

603

const expelled1 = await client.topK.add("popular_products",

604

"laptop_001", "phone_002", "tablet_003", "laptop_001", "headphones_004"

605

);

606

console.log("Expelled items:", expelled1); // null values initially

607

608

// Add more views with bulk operations

609

await client.topK.add("popular_products",

610

"laptop_001", "laptop_001", "phone_002", "watch_005", "camera_006",

611

"laptop_007", "phone_008", "tablet_009", "speaker_010", "mouse_011"

612

);

613

614

// Increment specific items

615

const expelled2 = await client.topK.incrBy("popular_products",

616

{ item: "laptop_001", increment: 5 },

617

{ item: "premium_headphones", increment: 3 },

618

{ item: "gaming_mouse", increment: 2 }

619

);

620

621

// Get current top-K list

622

const topProducts = await client.topK.list("popular_products");

623

console.log("Current top products:", topProducts);

624

625

// Get top-K with counts

626

const topWithCounts = await client.topK.listWithCount("popular_products");

627

console.log("Top products with counts:", topWithCounts);

628

// Format: [item1, count1, item2, count2, ...]

629

630

// Query specific items

631

const inTopK = await client.topK.query("popular_products",

632

"laptop_001", // Probably in top-K

633

"rare_item", // Probably not in top-K

634

"phone_002" // Check if still in top-K

635

);

636

console.log("In top-K:", inTopK); // [true, false, true] (example)

637

638

// Track page visits

639

await client.topK.reserve("popular_pages", 5); // Simple top-5 pages

640

641

// Simulate page visits

642

const pages = ["/home", "/products", "/about", "/contact", "/blog", "/pricing", "/features"];

643

for (let i = 0; i < 100; i++) {

644

const randomPage = pages[Math.floor(Math.random() * pages.length)];

645

await client.topK.add("popular_pages", randomPage);

646

}

647

648

// Get most visited pages

649

const topPages = await client.topK.listWithCount("popular_pages");

650

console.log("Most popular pages:", topPages);

651

652

// Get Top-K info

653

const info = await client.topK.info("popular_products");

654

console.log("Top-K info:", info);

655

```

656

657

## Use Cases and Best Practices

658

659

### Bloom Filters

660

- **Use for**: Cache filtering, duplicate detection, database query optimization

661

- **Best practices**: Reserve with appropriate capacity and error rate, consider Cuckoo filters if deletion is needed

662

- **Memory**: Very memory efficient, but no deletion support

663

664

### Count-Min Sketch

665

- **Use for**: Frequency estimation, heavy hitters detection, rate limiting

666

- **Best practices**: Choose width/depth based on error requirements, merge sketches for distributed counting

667

- **Memory**: Fixed memory usage regardless of item count

668

669

### Cuckoo Filters

670

- **Use for**: Set membership with deletion support, better than Bloom for small sets

671

- **Best practices**: Good alternative to Bloom filters, supports deletion, generally faster lookups

672

- **Memory**: Slightly more memory than Bloom filters but supports deletion

673

674

### T-Digest

675

- **Use for**: Percentile monitoring, SLA tracking, statistical analysis of streaming data

676

- **Best practices**: Higher compression for more accuracy, merge digests for distributed percentiles

677

- **Memory**: Bounded memory with configurable accuracy/memory trade-off

678

679

### Top-K

680

- **Use for**: Popular item tracking, trending analysis, heavy hitters identification

681

- **Best practices**: Set appropriate decay for temporal relevance, monitor expelled items

682

- **Memory**: Fixed memory for tracking exactly K items with frequency estimates

683

684

## Error Handling

685

686

All probabilistic data structures can throw errors for invalid parameters:

687

688

```typescript

689

try {

690

// Invalid error rate (must be 0 < rate < 1)

691

await client.bf.reserve("filter", 1.5, 1000);

692

} catch (error) {

693

console.error("Invalid error rate:", error.message);

694

}

695

696

try {

697

// Invalid quantile (must be 0.0 to 1.0)

698

await client.tDigest.quantile("digest", 1.5);

699

} catch (error) {

700

console.error("Invalid quantile:", error.message);

701

}

702

```