From b9e5c9a3d7834afb6e48fdb6d7d9d2fdc29bf9a8 Mon Sep 17 00:00:00 2001 From: Simon Prickett Date: Mon, 15 Aug 2022 13:39:28 +0100 Subject: [PATCH] Updates examples. (#2219) * Updates examples. * Added command link for hset. --- examples/README.md | 15 +- examples/blocking-list-pop.js | 32 ++-- examples/bloom-filter.js | 127 +++++++------- examples/command-with-modifiers.js | 33 ++-- examples/connect-as-acl-user.js | 28 ++- examples/count-min-sketch.js | 129 +++++++------- examples/cuckoo-filter.js | 130 +++++++------- examples/get-server-time.js | 16 +- examples/lua-multi-incr.js | 42 ++--- examples/managing-json.js | 127 +++++++------- examples/search-hashes.js | 147 ++++++++-------- examples/search-json.js | 267 +++++++++++++++-------------- examples/set-scan.js | 16 +- examples/sorted-set.js | 48 +++--- examples/stream-consumer-group.js | 139 +++++++-------- examples/stream-consumer.js | 99 ++++++----- examples/stream-producer.js | 89 +++++----- examples/time-series.js | 218 ++++++++++++----------- examples/topk.js | 191 +++++++++++---------- 19 files changed, 923 insertions(+), 970 deletions(-) diff --git a/examples/README.md b/examples/README.md index a026bc0b1c..089096d719 100644 --- a/examples/README.md +++ b/examples/README.md @@ -53,7 +53,7 @@ When adding a new example, please follow these guidelines: * Use semicolons * Use `async` and `await` * Use single quotes, `'hello'` not `"hello"` -* Place your example code in a single `async` function where possible, named according to the file name e.g. `add-to-stream.js` would contain `const addtoStream = async () => { ... };`, and call this function at the end of the file e.g. `addToStream();` +* Use [template literals](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals) when embedding expressions in strings * Unless your example requires a connection string, assume Redis is on the default localhost port 6379 with no password * Use meaningful example data, let's not use `foo`, `bar`, `baz` etc! * Leave an empty line at the end of your `.js` file @@ -71,18 +71,17 @@ Here's a starter template for adding a new example, imagine this is stored in `d // Set up the data in redis-cli using these commands: // +// +// Alternatively, add code that sets up the data. import { createClient } from 'redis'; -async function doSomething() { - const client = createClient(); +const client = createClient(); - await client.connect(); +await client.connect(); - // Add your example code here... +// Add your example code here... - await client.quit(); -} +await client.quit(); -doSomething(); ``` diff --git a/examples/blocking-list-pop.js b/examples/blocking-list-pop.js index 59dde3274a..099c73a2a9 100644 --- a/examples/blocking-list-pop.js +++ b/examples/blocking-list-pop.js @@ -6,27 +6,25 @@ import { createClient, commandOptions } from 'redis'; -async function blockingListPop() { - const client = createClient(); +const client = createClient(); - await client.connect(); +await client.connect(); - const keyName = 'keyName'; +const keyName = 'keyName'; - const blpopPromise = client.blPop( - commandOptions({ isolated: true }), - keyName, - 0 - ); +const blpopPromise = client.blPop( + commandOptions({ isolated: true }), + keyName, + 0 +); - await client.lPush(keyName, 'value'); +await client.lPush(keyName, 'value'); - await blpopPromise; +const listItem = await blpopPromise; - console.log('blpopPromise resolved'); - console.log(keyName); +console.log('blpopPromise resolved'); +// listItem will be: +// {"key":"keyName","element":"value"} +console.log(`listItem is '${JSON.stringify(listItem)}'`); - await client.quit(); -} - -blockingListPop(); +await client.quit(); diff --git a/examples/bloom-filter.js b/examples/bloom-filter.js index db55c519c3..cf5f1940b3 100644 --- a/examples/bloom-filter.js +++ b/examples/bloom-filter.js @@ -1,79 +1,80 @@ // This example demonstrates the use of the Bloom Filter -// in the RedisBloom module (https://redisbloom.io/) +// in the RedisBloom module (https://redis.io/docs/stack/bloom/) import { createClient } from 'redis'; -async function bloomFilter() { - const client = createClient(); +const client = createClient(); - await client.connect(); +await client.connect(); - // Delete any pre-existing Bloom Filter. - await client.del('mybloom'); +// Delete any pre-existing Bloom Filter. +await client.del('mybloom'); - // Reserve a Bloom Filter with configurable error rate and capacity. - // https://oss.redis.com/redisbloom/Bloom_Commands/#bfreserve - try { - await client.bf.reserve('mybloom', 0.01, 1000); - console.log('Reserved Bloom Filter.'); - } catch (e) { - if (e.message.endsWith('item exists')) { - console.log('Bloom Filter already reserved.'); - } else { - console.log('Error, maybe RedisBloom is not installed?:'); - console.log(e); - } +// Reserve a Bloom Filter with configurable error rate and capacity. +// https://redis.io/commands/bf.reserve/ +try { + await client.bf.reserve('mybloom', 0.01, 1000); + console.log('Reserved Bloom Filter.'); +} catch (e) { + if (e.message.endsWith('item exists')) { + console.log('Bloom Filter already reserved.'); + } else { + console.log('Error, maybe RedisBloom is not installed?:'); + console.log(e); } +} - // Add items to Bloom Filter individually with BF.ADD command. - await Promise.all([ - client.bf.add('mybloom', 'leibale'), - client.bf.add('mybloom', 'simon'), - client.bf.add('mybloom', 'guy'), - client.bf.add('mybloom', 'suze'), - client.bf.add('mybloom', 'brian'), - client.bf.add('mybloom', 'steve'), - client.bf.add('mybloom', 'kyle'), - client.bf.add('mybloom', 'josefin'), - client.bf.add('mybloom', 'alex'), - client.bf.add('mybloom', 'nava'), - ]); - - // Add multiple items to Bloom Filter at once with BF.MADD command. - await client.bf.mAdd('mybloom', [ - 'kaitlyn', - 'rachel' - ]); +// Add items to Bloom Filter individually with BF.ADD command. +// https://redis.io/commands/bf.add/ +await Promise.all([ + client.bf.add('mybloom', 'leibale'), + client.bf.add('mybloom', 'simon'), + client.bf.add('mybloom', 'guy'), + client.bf.add('mybloom', 'suze'), + client.bf.add('mybloom', 'brian'), + client.bf.add('mybloom', 'steve'), + client.bf.add('mybloom', 'kyle'), + client.bf.add('mybloom', 'josefin'), + client.bf.add('mybloom', 'alex'), + client.bf.add('mybloom', 'nava'), +]); - console.log('Added members to Bloom Filter.'); +// Add multiple items to Bloom Filter at once with BF.MADD command. +// https://redis.io/commands/bf.madd/ +await client.bf.mAdd('mybloom', [ + 'kaitlyn', + 'rachel' +]); - // Check whether a member exists with the BF.EXISTS command. - const simonExists = await client.bf.exists('mybloom', 'simon'); - console.log(`simon ${simonExists ? 'may' : 'does not'} exist in the Bloom Filter.`); +console.log('Added members to Bloom Filter.'); - // Check whether multiple members exist with the BF.MEXISTS command: - const [ lanceExists, leibaleExists ] = await client.bf.mExists('mybloom', [ - 'lance', - 'leibale' - ]); +// Check whether a member exists with the BF.EXISTS command. +// https://redis.io/commands/bf.exists/ +const simonExists = await client.bf.exists('mybloom', 'simon'); +console.log(`simon ${simonExists ? 'may' : 'does not'} exist in the Bloom Filter.`); - console.log(`lance ${lanceExists ? 'may' : 'does not'} exist in the Bloom Filter.`); - console.log(`leibale ${leibaleExists ? 'may' : 'does not'} exist in the Bloom Filter.`); +// Check whether multiple members exist with the BF.MEXISTS command. +// https://redis.io/commands/bf.mexists/ +const [ lanceExists, leibaleExists ] = await client.bf.mExists('mybloom', [ + 'lance', + 'leibale' +]); - // Get stats for the Bloom Filter with the BF.INFO command: - const info = await client.bf.info('mybloom'); - // info looks like this: - // - // { - // capacity: 1000, - // size: 1531, - // numberOfFilters: 1, - // numberOfInsertedItems: 12, - // expansionRate: 2 - // } - console.log(info); +console.log(`lance ${lanceExists ? 'may' : 'does not'} exist in the Bloom Filter.`); +console.log(`leibale ${leibaleExists ? 'may' : 'does not'} exist in the Bloom Filter.`); - await client.quit(); -} +// Get stats for the Bloom Filter with the BF.INFO command. +// https://redis.io/commands/bf.info/ +const info = await client.bf.info('mybloom'); +// info looks like this: +// +// { +// capacity: 1000, +// size: 1531, +// numberOfFilters: 1, +// numberOfInsertedItems: 12, +// expansionRate: 2 +// } +console.log(info); -bloomFilter(); +await client.quit(); diff --git a/examples/command-with-modifiers.js b/examples/command-with-modifiers.js index 3194023381..974f78dc5d 100644 --- a/examples/command-with-modifiers.js +++ b/examples/command-with-modifiers.js @@ -3,28 +3,23 @@ import { createClient } from 'redis'; -async function commandWithModifiers() { - const client = createClient(); +const client = createClient(); - await client.connect(); - await client.del('mykey'); +await client.connect(); +await client.del('mykey'); - let result = await client.set('mykey', 'myvalue', { - EX: 60, - GET: true - }); +let result = await client.set('mykey', 'myvalue', { + EX: 60, + GET: true +}); - console.log(result); //nil +console.log(result); //null - result = await client.set('mykey', 'newvalue', { - EX: 60, - GET: true - }); +result = await client.set('mykey', 'newvalue', { + EX: 60, + GET: true +}); - console.log(result); //myvalue - - await client.quit(); -} - -commandWithModifiers(); +console.log(result); //myvalue +await client.quit(); diff --git a/examples/connect-as-acl-user.js b/examples/connect-as-acl-user.js index 26e1e443b0..df46aa1e28 100644 --- a/examples/connect-as-acl-user.js +++ b/examples/connect-as-acl-user.js @@ -7,24 +7,20 @@ import { createClient } from 'redis'; -async function connectWithACLUser() { - const client = createClient({ - url: 'redis://testuser:testpassword@127.0.0.1:6379' - }); +const client = createClient({ + url: 'redis://testuser:testpassword@127.0.0.1:6379' +}); - await client.connect(); +await client.connect(); - // Returns PONG - console.log(`Response from PING command: ${await client.ping()}`); +// Returns PONG +console.log(`Response from PING command: ${await client.ping()}`); - try { - // This will error as this user is not allowed to run this command... - console.log(`Response from GET command: ${await client.get('somekey')}`); - } catch (e) { - console.log(`GET command failed: ${e.message}`); - } - - await client.quit(); +try { + // This will error as this user is not allowed to run this command... + console.log(`Response from GET command: ${await client.get('somekey')}`); +} catch (e) { + console.log(`GET command failed: ${e.message}`); } -connectWithACLUser(); +await client.quit(); diff --git a/examples/count-min-sketch.js b/examples/count-min-sketch.js index 7deb644355..f88a148986 100644 --- a/examples/count-min-sketch.js +++ b/examples/count-min-sketch.js @@ -1,83 +1,80 @@ // This example demonstrates the use of the Count-Min Sketch -// in the RedisBloom module (https://redisbloom.io/) +// in the RedisBloom module (https://redis.io/docs/stack/bloom/) import { createClient } from 'redis'; -async function countMinSketch() { - const client = createClient(); +const client = createClient(); - await client.connect(); +await client.connect(); - // Delete any pre-existing Count-Min Sketch. - await client.del('mycms'); +// Delete any pre-existing Count-Min Sketch. +await client.del('mycms'); - // Initialize a Count-Min Sketch with error rate and probability: - // https://oss.redis.com/redisbloom/CountMinSketch_Commands/#cmsinitbyprob - try { - await client.cms.initByProb('mycms', 0.001, 0.01); - console.log('Initialized Count-Min Sketch.'); - } catch (e) { - console.log('Error, maybe RedisBloom is not installed?:'); - console.log(e); - } +// Initialize a Count-Min Sketch with error rate and probability: +// https://redis.io/commands/cms.initbyprob/ +try { + await client.cms.initByProb('mycms', 0.001, 0.01); + console.log('Reserved Count Min Sketch.'); +} catch (e) { + console.log('Error, maybe RedisBloom is not installed?:'); + console.log(e); +} - const teamMembers = [ - 'leibale', - 'simon', - 'guy', - 'suze', - 'brian', - 'steve', - 'kyleb', - 'kyleo', - 'josefin', - 'alex', - 'nava', - 'lance', - 'rachel', - 'kaitlyn' - ]; +const teamMembers = [ + 'leibale', + 'simon', + 'guy', + 'suze', + 'brian', + 'steve', + 'kyleb', + 'kyleo', + 'josefin', + 'alex', + 'nava', + 'lance', + 'rachel', + 'kaitlyn' +]; - // Store actual counts for comparison with CMS. - let actualCounts = {}; +// Store actual counts for comparison with CMS. +let actualCounts = {}; - // Randomly emit a team member and count them with the CMS. - for (let n = 0; n < 1000; n++) { - const teamMember = teamMembers[Math.floor(Math.random() * teamMembers.length)]; - await client.cms.incrBy('mycms', { - item: teamMember, - incrementBy: 1 - }); +// Randomly emit a team member and count them with the CMS. +// https://redis.io/commands/cms.incrby/ +for (let n = 0; n < 1000; n++) { + const teamMember = teamMembers[Math.floor(Math.random() * teamMembers.length)]; + await client.cms.incrBy('mycms', { + item: teamMember, + incrementBy: 1 + }); - actualCounts[teamMember] = actualCounts[teamMember] ? actualCounts[teamMember] + 1 : 1; + actualCounts[teamMember] = actualCounts[teamMember] ? actualCounts[teamMember] + 1 : 1; - console.log(`Incremented score for ${teamMember}.`); - } + console.log(`Incremented score for ${teamMember}.`); +} - // Get count estimate for some team members: - // https://oss.redis.com/redisbloom/CountMinSketch_Commands/#cmsquery - const [ alexCount, rachelCount ] = await client.cms.query('mycms', [ - 'simon', - 'lance' - ]); +// Get count estimate for some team members: +// https://redis.io/commands/cms.query/ +const [ alexCount, rachelCount ] = await client.cms.query('mycms', [ + 'alex', + 'rachel' +]); - console.log(`Count estimate for alex: ${alexCount} (actual ${actualCounts.alex}).`); - console.log(`Count estimate for rachel: ${rachelCount} (actual ${actualCounts.rachel}).`); +console.log(`Count estimate for alex: ${alexCount} (actual ${actualCounts.alex}).`); +console.log(`Count estimate for rachel: ${rachelCount} (actual ${actualCounts.rachel}).`); - // Get overall information about the Count-Min Sketch: - // https://oss.redis.com/redisbloom/CountMinSketch_Commands/#cmsinfo - const info = await client.cms.info('mycms'); - console.log('Count-Min Sketch info:'); +// Get overall information about the Count-Min Sketch: +// https://redis.io/commands/cms.info/ +const info = await client.cms.info('mycms'); +console.log('Count-Min Sketch info:'); - // info looks like this: - // { - // width: 2000, - // depth: 7, - // count: 1000 - // } - console.log(info); - - await client.quit(); -} +// info looks like this: +// { +// width: 2000, +// depth: 7, +// count: 1000 +// } +console.log(info); -countMinSketch(); +await client.quit(); diff --git a/examples/cuckoo-filter.js b/examples/cuckoo-filter.js index e2262a9f02..87976f3fef 100644 --- a/examples/cuckoo-filter.js +++ b/examples/cuckoo-filter.js @@ -1,81 +1,79 @@ // This example demonstrates the use of the Cuckoo Filter -// in the RedisBloom module (https://redisbloom.io/) +// in the RedisBloom module (https://redis.io/docs/stack/bloom/) import { createClient } from 'redis'; -async function cuckooFilter() { - const client = createClient(); +const client = createClient(); - await client.connect(); +await client.connect(); - // Delete any pre-existing Cuckoo Filter. - await client.del('mycuckoo'); +// Delete any pre-existing Cuckoo Filter. +await client.del('mycuckoo'); - // Reserve a Cuckoo Filter with a capacity of 10000 items. - // https://oss.redis.com/redisbloom/Cuckoo_Commands/#cfreserve - try { - await client.cf.reserve('mycuckoo', 10000); - console.log('Reserved Cuckoo Filter.'); - } catch (e) { - console.log('Error, maybe RedisBloom is not installed?:'); - console.log(e); - } - - // Add items to Cuckoo Filter individually with CF.ADD command. - https://oss.redis.com/redisbloom/Cuckoo_Commands/#cfadd - await Promise.all([ - client.cf.add('mycuckoo', 'leibale'), - client.cf.add('mycuckoo', 'simon'), - client.cf.add('mycuckoo', 'guy'), - client.cf.add('mycuckoo', 'suze'), - client.cf.add('mycuckoo', 'brian'), - client.cf.add('mycuckoo', 'steve'), - client.cf.add('mycuckoo', 'kyle'), - client.cf.add('mycuckoo', 'josefin'), - client.cf.add('mycuckoo', 'alex'), - client.cf.add('mycuckoo', 'nava'), - ]); +// Reserve a Cuckoo Filter with a capacity of 10000 items. +// https://redis.io/commands/cf.reserve/ +try { + await client.cf.reserve('mycuckoo', 10000); + console.log('Reserved Cuckoo Filter.'); +} catch (e) { + console.log('Error, maybe RedisBloom is not installed?:'); + console.log(e); +} - // Add items to the Cuckoo Filter only if they don't exist in it... - // https://oss.redis.com/redisbloom/Cuckoo_Commands/#cfaddnx - const nxReply = await Promise.all([ - client.cf.addNX('mycuckoo', 'kaitlyn'), // New - client.cf.addNX('mycuckoo', 'rachel'), // New - client.cf.addNX('mycuckoo', 'brian') // Previously added - ]); +// Add items to Cuckoo Filter individually with CF.ADD command. +// https://redis.io/commands/cf.add/ +await Promise.all([ + client.cf.add('mycuckoo', 'leibale'), + client.cf.add('mycuckoo', 'simon'), + client.cf.add('mycuckoo', 'guy'), + client.cf.add('mycuckoo', 'suze'), + client.cf.add('mycuckoo', 'brian'), + client.cf.add('mycuckoo', 'steve'), + client.cf.add('mycuckoo', 'kyle'), + client.cf.add('mycuckoo', 'josefin'), + client.cf.add('mycuckoo', 'alex'), + client.cf.add('mycuckoo', 'nava'), +]); - console.log('Added members to Cuckoo Filter.'); - console.log('nxReply:'); +// Add items to the Cuckoo Filter only if they don't exist in it... +// https://redis.io/commands/cf.addnx/ +const nxReply = await Promise.all([ + client.cf.addNX('mycuckoo', 'kaitlyn'), // New + client.cf.addNX('mycuckoo', 'rachel'), // New + client.cf.addNX('mycuckoo', 'brian') // Previously added +]); - // nxReply looks like this: - // [ - // true, - // true, - // false - // ] - console.log(nxReply); +console.log('Added members to Cuckoo Filter.'); +console.log('nxReply:'); - // Check whether a member exists with the CF.EXISTS command. - const simonExists = await client.bf.exists('mycuckoo', 'simon'); - console.log(`simon ${simonExists ? 'may' : 'does not'} exist in the Cuckoo Filter.`); +// nxReply looks like this: +// [ +// true, +// true, +// false +// ] +console.log(nxReply); - // Get stats for the Cuckoo Filter with the CF.INFO command: - const info = await client.cf.info('mycuckoo'); +// Check whether a member exists with the CF.EXISTS command. +// https://redis.io/commands/cf.exists/ +const simonExists = await client.bf.exists('mycuckoo', 'simon'); +console.log(`simon ${simonExists ? 'may' : 'does not'} exist in the Cuckoo Filter.`); - // info looks like this: - // { - // size: 16440, - // numberOfBuckets: 8192, - // numberOfFilters: 1, - // numberOfInsertedItems: 12, - // numberOfDeletedItems: 0, - // bucketSize: 2, - // expansionRate: 1, - // maxIteration: 20 - // } - console.log(info); +// Get stats for the Cuckoo Filter with the CF.INFO command: +// https://redis.io/commands/cf.info/ +const info = await client.cf.info('mycuckoo'); - await client.quit(); -} +// info looks like this: +// { +// size: 16440, +// numberOfBuckets: 8192, +// numberOfFilters: 1, +// numberOfInsertedItems: 12, +// numberOfDeletedItems: 0, +// bucketSize: 2, +// expansionRate: 1, +// maxIteration: 20 +// } +console.log(info); -cuckooFilter(); +await client.quit(); diff --git a/examples/get-server-time.js b/examples/get-server-time.js index c6b7956c83..967859f013 100644 --- a/examples/get-server-time.js +++ b/examples/get-server-time.js @@ -2,15 +2,11 @@ import { createClient } from 'redis'; -async function getServerTime() { - const client = createClient(); - await client.connect(); +const client = createClient(); +await client.connect(); - const serverTime = await client.time(); - // 2022-02-25T12:57:40.000Z { microseconds: 351346 } - console.log(serverTime); +const serverTime = await client.time(); +// 2022-02-25T12:57:40.000Z { microseconds: 351346 } +console.log(serverTime); - await client.quit(); -} - -getServerTime(); +await client.quit(); diff --git a/examples/lua-multi-incr.js b/examples/lua-multi-incr.js index ec433c27ea..8eb1092c29 100644 --- a/examples/lua-multi-incr.js +++ b/examples/lua-multi-incr.js @@ -3,29 +3,25 @@ import { createClient, defineScript } from 'redis'; -async function luaMultiIncr() { - const client = createClient({ - scripts: { - mincr: defineScript({ - NUMBER_OF_KEYS: 2, - SCRIPT: - 'return {' + - 'redis.pcall("INCRBY", KEYS[1], ARGV[1]),' + - 'redis.pcall("INCRBY", KEYS[2], ARGV[1])' + - '}', - transformArguments(key1, key2, increment) { - return [key1, key2, increment.toString()]; - }, - }), - }, - }); +const client = createClient({ + scripts: { + mincr: defineScript({ + NUMBER_OF_KEYS: 2, + SCRIPT: + 'return {' + + 'redis.pcall("INCRBY", KEYS[1], ARGV[1]),' + + 'redis.pcall("INCRBY", KEYS[2], ARGV[1])' + + '}', + transformArguments(key1, key2, increment) { + return [key1, key2, increment.toString()]; + }, + }), + }, +}); - await client.connect(); +await client.connect(); - await client.set('mykey', '5'); - console.log(await client.mincr('mykey', 'myotherkey', 10)); // [ 15, 10 ] +await client.set('mykey', '5'); +console.log(await client.mincr('mykey', 'myotherkey', 10)); // [ 15, 10 ] - await client.quit(); -} - -luaMultiIncr(); +await client.quit(); diff --git a/examples/managing-json.js b/examples/managing-json.js index 44978a94f0..81949d5c22 100644 --- a/examples/managing-json.js +++ b/examples/managing-json.js @@ -2,80 +2,75 @@ import { createClient } from 'redis'; -async function managingJSON() { - const client = createClient(); +const client = createClient(); - await client.connect(); - await client.del('noderedis:jsondata'); +await client.connect(); +await client.del('noderedis:jsondata'); - // Store a JSON object... - await client.json.set('noderedis:jsondata', '$', { - name: 'Roberta McDonald', - pets: [ - { - name: 'Fluffy', - species: 'dog', - age: 5, - isMammal: true - }, - { - name: 'Rex', - species: 'dog', - age: 3, - isMammal: true - }, - { - name: 'Goldie', - species: 'fish', - age: 2, - isMammal: false - } - ], - address: { - number: 99, - street: 'Main Street', - city: 'Springfield', - state: 'OH', - country: 'USA' +// Store a JSON object... +await client.json.set('noderedis:jsondata', '$', { + name: 'Roberta McDonald', + pets: [ + { + name: 'Fluffy', + species: 'dog', + age: 5, + isMammal: true + }, + { + name: 'Rex', + species: 'dog', + age: 3, + isMammal: true + }, + { + name: 'Goldie', + species: 'fish', + age: 2, + isMammal: false } - }); + ], + address: { + number: 99, + street: 'Main Street', + city: 'Springfield', + state: 'OH', + country: 'USA' + } +}); - // Retrieve the name and age of the second pet in the pets array. - let results = await client.json.get('noderedis:jsondata', { - path: [ - '.pets[1].name', - '.pets[1].age' - ] - }); +// Retrieve the name and age of the second pet in the pets array. +let results = await client.json.get('noderedis:jsondata', { + path: [ + '$.pets[1].name', + '$.pets[1].age' + ] +}); - // { '.pets[1].name': 'Rex', '.pets[1].age': 3 } - console.log(results); +// { '$.pets[1].name': [ 'Rex' ], '$.pets[1].age': [ 3 ] } +console.log(results); - // Goldie had a birthday, increment the age... - await client.json.numIncrBy('noderedis:jsondata', '.pets[2].age', 1); - results = await client.json.get('noderedis:jsondata', { - path: '.pets[2].age' - }); +// Goldie had a birthday, increment the age... +await client.json.numIncrBy('noderedis:jsondata', '$.pets[2].age', 1); +results = await client.json.get('noderedis:jsondata', { + path: '$.pets[2].age' +}); - // Goldie is 3 years old now. - console.log(`Goldie is ${JSON.stringify(results)} years old now.`); +// Goldie is 3 years old now. +console.log(`Goldie is ${JSON.stringify(results[0])} years old now.`); - // Add a new pet... - await client.json.arrAppend('noderedis:jsondata', '.pets', { - name: 'Robin', - species: 'bird', - isMammal: false, - age: 1 - }); +// Add a new pet... +await client.json.arrAppend('noderedis:jsondata', '$.pets', { + name: 'Robin', + species: 'bird', + isMammal: false, + age: 1 +}); - // How many pets do we have now? - const numPets = await client.json.arrLen('noderedis:jsondata', '.pets'); +// How many pets do we have now? +const numPets = await client.json.arrLen('noderedis:jsondata', '$.pets'); - // We now have 4 pets. - console.log(`We now have ${numPets} pets.`); - - await client.quit(); -} - -managingJSON(); +// We now have 4 pets. +console.log(`We now have ${numPets} pets.`); +await client.quit(); diff --git a/examples/search-hashes.js b/examples/search-hashes.js index 46d5e598cf..85e6106a99 100644 --- a/examples/search-hashes.js +++ b/examples/search-hashes.js @@ -3,89 +3,86 @@ import { createClient, SchemaFieldTypes } from 'redis'; -async function searchHashes() { - const client = createClient(); +const client = createClient(); - await client.connect(); +await client.connect(); - // Create an index... - try { - // Documentation: https://oss.redis.com/redisearch/Commands/#ftcreate - await client.ft.create('idx:animals', { - name: { - type: SchemaFieldTypes.TEXT, - sortable: true - }, - species: SchemaFieldTypes.TAG, - age: SchemaFieldTypes.NUMERIC - }, { - ON: 'HASH', - PREFIX: 'noderedis:animals' - }); - } catch (e) { - if (e.message === 'Index already exists') { - console.log('Index exists already, skipped creation.'); - } else { - // Something went wrong, perhaps RediSearch isn't installed... - console.error(e); - process.exit(1); - } +// Create an index... +try { + // Documentation: https://redis.io/commands/ft.create/ + await client.ft.create('idx:animals', { + name: { + type: SchemaFieldTypes.TEXT, + sortable: true + }, + species: SchemaFieldTypes.TAG, + age: SchemaFieldTypes.NUMERIC + }, { + ON: 'HASH', + PREFIX: 'noderedis:animals' + }); +} catch (e) { + if (e.message === 'Index already exists') { + console.log('Index exists already, skipped creation.'); + } else { + // Something went wrong, perhaps RediSearch isn't installed... + console.error(e); + process.exit(1); } +} - // Add some sample data... - await Promise.all([ - client.hSet('noderedis:animals:1', {name: 'Fluffy', species: 'cat', age: 3}), - client.hSet('noderedis:animals:2', {name: 'Ginger', species: 'cat', age: 4}), - client.hSet('noderedis:animals:3', {name: 'Rover', species: 'dog', age: 9}), - client.hSet('noderedis:animals:4', {name: 'Fido', species: 'dog', age: 7}) - ]); +// Add some sample data... +// https://redis.io/commands/hset/ +await Promise.all([ + client.hSet('noderedis:animals:1', {name: 'Fluffy', species: 'cat', age: 3}), + client.hSet('noderedis:animals:2', {name: 'Ginger', species: 'cat', age: 4}), + client.hSet('noderedis:animals:3', {name: 'Rover', species: 'dog', age: 9}), + client.hSet('noderedis:animals:4', {name: 'Fido', species: 'dog', age: 7}) +]); - // Perform a search query, find all the dogs... sort by age, descending. - // Documentation: https://oss.redis.com/redisearch/Commands/#ftsearch - // Query syntax: https://oss.redis.com/redisearch/Query_Syntax/ - const results = await client.ft.search( - 'idx:animals', - '@species:{dog}', - { - SORTBY: { - BY: 'age', - DIRECTION: 'DESC' // or 'ASC' (default if DIRECTION is not present) - } +// Perform a search query, find all the dogs... sort by age, descending. +// Documentation: https://redis.io/commands/ft.search/ +// Query syntax: https://redis.io/docs/stack/search/reference/query_syntax/ +const results = await client.ft.search( + 'idx:animals', + '@species:{dog}', + { + SORTBY: { + BY: 'age', + DIRECTION: 'DESC' // or 'ASC (default if DIRECTION is not present) } - ); + } +); - // results: - // { - // total: 2, - // documents: [ - // { - // id: 'noderedis:animals:3', - // value: { - // age: '9', - // name: 'Rover', - // species: 'dog' - // } - // }, - // { - // id: 'noderedis:animals:4', - // value: { - // age: '7', - // name: 'Fido', - // species: 'dog' - // } - // } - // ] - // } - - console.log(`Results found: ${results.total}.`); +// results: +// { +// total: 2, +// documents: [ +// { +// id: 'noderedis:animals:3', +// value: { +// name: 'Rover', +// species: 'dog', +// age: '9' +// } +// }, +// { +// id: 'noderedis:animals:4', +// value: { +// name: 'Fido', +// species: 'dog', +// age: '7' +// } +// } +// ] +// } - for (const doc of results.documents) { - // noderedis:animals:3: Rover, 9 years old. - // noderedis:animals:4: Fido, 7 years old. - console.log(`${doc.id}: ${doc.value.name}, ${doc.value.age} years old.`); - } +console.log(`Results found: ${results.total}.`); - await client.quit(); +for (const doc of results.documents) { + // noderedis:animals:3: Rover, 9 years old. + // noderedis:animals:4: Fido, 7 years old. + console.log(`${doc.id}: ${doc.value.name}, ${doc.value.age} years old.`); } -searchHashes(); +await client.quit(); diff --git a/examples/search-json.js b/examples/search-json.js index a0a29c6929..6205a1f110 100644 --- a/examples/search-json.js +++ b/examples/search-json.js @@ -1,147 +1,148 @@ // This example demonstrates how to use RediSearch and RedisJSON together. +// Requires both the RediSearch and RedisJSON modules: +// https://redis.io/docs/stack/search/ +// https://redis.io/docs/stack/json/ import { createClient, SchemaFieldTypes, AggregateGroupByReducers, AggregateSteps } from 'redis'; -async function searchJSON() { - const client = createClient(); +const client = createClient(); - await client.connect(); +await client.connect(); - // Create an index. - try { - await client.ft.create('idx:users', { - '$.name': { - type: SchemaFieldTypes.TEXT, - SORTABLE: 'UNF' - }, - '$.age': { - type: SchemaFieldTypes.NUMERIC, - AS: 'age' - }, - '$.coins': { - type: SchemaFieldTypes.NUMERIC, - AS: 'coins' - }, - '$.email': { - type: SchemaFieldTypes.TAG, - AS: 'email' - } - }, { - ON: 'JSON', - PREFIX: 'noderedis:users' - }); - } catch (e) { - if (e.message === 'Index already exists') { - console.log('Index exists already, skipped creation.'); - } else { - // Something went wrong, perhaps RediSearch isn't installed... - console.error(e); - process.exit(1); +// Create an index. +// https://redis.io/commands/ft.create/ +try { + await client.ft.create('idx:users', { + '$.name': { + type: SchemaFieldTypes.TEXT, + SORTABLE: 'UNF' + }, + '$.age': { + type: SchemaFieldTypes.NUMERIC, + AS: 'age' + }, + '$.coins': { + type: SchemaFieldTypes.NUMERIC, + AS: 'coins' + }, + '$.email': { + type: SchemaFieldTypes.TAG, + AS: 'email' } + }, { + ON: 'JSON', + PREFIX: 'noderedis:users' + }); +} catch (e) { + if (e.message === 'Index already exists') { + console.log('Index exists already, skipped creation.'); + } else { + // Something went wrong, perhaps RediSearch isn't installed... + console.error(e); + process.exit(1); } +} - // Add some users. - await Promise.all([ - client.json.set('noderedis:users:1', '$', { - name: 'Alice', - age: 32, - coins: 100, - email: 'alice@nonexist.com' - }), - client.json.set('noderedis:users:2', '$', { - name: 'Bob', - age: 23, - coins: 15, - email: 'bob@somewhere.gov' - }) - ]); +// Add some users. +// https://redis.io/commands/json.set/ +await Promise.all([ + client.json.set('noderedis:users:1', '$', { + name: 'Alice', + age: 32, + coins: 100, + email: 'alice@nonexist.com' + }), + client.json.set('noderedis:users:2', '$', { + name: 'Bob', + age: 23, + coins: 15, + email: 'bob@somewhere.gov' + }) +]); - // Search all users under 30 - console.log('Users under 30 years old:'); - console.log( - // https://oss.redis.com/redisearch/Commands/#ftsearch - JSON.stringify( - await client.ft.search('idx:users', '@age:[0 30]'), - null, - 2 - ) - ); - // { - // "total": 1, - // "documents": [ - // { - // "id": "noderedis:users:2", - // "value": { - // "name": "Bob", - // "age": 23, - // "coins": 15, - // "email": "bob@somewhere.gov" - // } - // } - // ] - // } +// Search all users under 30 +console.log('Users under 30 years old:'); +console.log( + // https://redis.io/commands/ft.search/ + JSON.stringify( + await client.ft.search('idx:users', '@age:[0 30]'), + null, + 2 + ) +); +// { +// "total": 1, +// "documents": [ +// { +// "id": "noderedis:users:2", +// "value": { +// "name": "Bob", +// "age": 23, +// "coins": 15, +// "email": "bob@somewhere.gov" +// } +// } +// ] +// } - // Find a user by email - note we need to escape . and @ characters - // in the email address. This applies for other punctuation too. - // https://oss.redis.com/redisearch/Tags/#including_punctuation_in_tags - console.log('Users with email "bob@somewhere.gov":'); - const emailAddress = 'bob@somewhere.gov'.replace(/[.@]/g, '\\$&'); - console.log( - JSON.stringify( - await client.ft.search('idx:users', `@email:{${emailAddress}}`), - null, - 2 - ) - ); - // { - // "total": 1, - // "documents": [ - // { - // "id": "noderedis:users:2", - // "value": { - // "name": "Bob", - // "age": 23, - // "coins": 15, - // "email": "bob@somewhere.gov" - // } - // } - // ] - // } +// Find a user by email - note we need to escape . and @ characters +// in the email address. This applies for other punctuation too. +// https://redis.io/docs/stack/search/reference/tags/#including-punctuation-in-tags +console.log('Users with email "bob@somewhere.gov":'); +const emailAddress = 'bob@somewhere.gov'.replace(/[.@]/g, '\\$&'); +console.log( + JSON.stringify( + await client.ft.search('idx:users', `@email:{${emailAddress}}`), + null, + 2 + ) +); +// { +// "total": 1, +// "documents": [ +// { +// "id": "noderedis:users:2", +// "value": { +// "name": "Bob", +// "age": 23, +// "coins": 15, +// "email": "bob@somewhere.gov" +// } +// } +// ] +// } - // Some aggregrations, what's the average age and total number of coins... - // https://oss.redis.com/redisearch/Commands/#ftaggregate - console.log('Aggregation Demo:'); - console.log( - JSON.stringify( - await client.ft.aggregate('idx:users', '*', { - STEPS: [{ - type: AggregateSteps.GROUPBY, - REDUCE: [{ - type: AggregateGroupByReducers.AVG, - property: 'age', - AS: 'averageAge' - }, { - type: AggregateGroupByReducers.SUM, - property: 'coins', - AS: 'totalCoins' - }] +// Some aggregrations, what's the average age and total number of coins... +// https://redis.io/commands/ft.aggregate/ +console.log('Aggregation Demo:'); +console.log( + JSON.stringify( + await client.ft.aggregate('idx:users', '*', { + STEPS: [{ + type: AggregateSteps.GROUPBY, + REDUCE: [{ + type: AggregateGroupByReducers.AVG, + property: 'age', + AS: 'averageAge' + }, { + type: AggregateGroupByReducers.SUM, + property: 'coins', + AS: 'totalCoins' }] - }), - null, - 2 - ) - ); - // { - // "total": 1, - // "results": [ - // { - // "averageAge": "27.5", - // "totalCoins": "115" - // } - // ] - // } - - await client.quit(); -} + }] + }), + null, + 2 + ) +); +// { +// "total": 1, +// "results": [ +// { +// "averageAge": "27.5", +// "totalCoins": "115" +// } +// ] +// } -searchJSON(); +await client.quit(); diff --git a/examples/set-scan.js b/examples/set-scan.js index 3cca05b152..73f6c44344 100644 --- a/examples/set-scan.js +++ b/examples/set-scan.js @@ -4,16 +4,12 @@ import { createClient } from 'redis'; -async function setScan() { - const client = createClient(); - await client.connect(); +const client = createClient(); +await client.connect(); - const setName = 'setName'; - for await (const member of client.sScanIterator(setName)) { - console.log(member); - } - - await client.quit(); +const setName = 'setName'; +for await (const member of client.sScanIterator(setName)) { + console.log(member); } -setScan(); +await client.quit(); diff --git a/examples/sorted-set.js b/examples/sorted-set.js index e2c4f14511..eb1f82867c 100644 --- a/examples/sorted-set.js +++ b/examples/sorted-set.js @@ -3,33 +3,29 @@ import { createClient } from 'redis'; -async function addToSortedSet() { - const client = createClient(); - await client.connect(); +const client = createClient(); +await client.connect(); - await client.zAdd('mysortedset', [ - { - score: 99, - value: 'Ninety Nine' - }, - { - score: 100, - value: 'One Hundred' - }, - { - score: 101, - value: 'One Hundred and One' - } - ]); - - // Get all of the values/scores from the sorted set using - // the scan approach: - // https://redis.io/commands/zscan - for await (const memberWithScore of client.zScanIterator('mysortedset')) { - console.log(memberWithScore); +await client.zAdd('mysortedset', [ + { + score: 99, + value: 'Ninety Nine' + }, + { + score: 100, + value: 'One Hundred' + }, + { + score: 101, + value: 'One Hundred and One' } - - await client.quit(); +]); + +// Get all of the values/scores from the sorted set using +// the scan approach: +// https://redis.io/commands/zscan +for await (const memberWithScore of client.zScanIterator('mysortedset')) { + console.log(memberWithScore); } -addToSortedSet(); +await client.quit(); diff --git a/examples/stream-consumer-group.js b/examples/stream-consumer-group.js index 0dc8ff20fe..0161b5b4d3 100644 --- a/examples/stream-consumer-group.js +++ b/examples/stream-consumer-group.js @@ -1,4 +1,6 @@ // A sample stream consumer using the blocking variant of XREADGROUP. +// https://redis.io/commands/xreadgroup/ + // This consumer works in collaboration with other instances of itself // in the same consumer group such that the group as a whole receives // every entry from the stream. @@ -20,85 +22,84 @@ import { createClient, commandOptions } from 'redis'; -async function streamConsumerGroup() { - const client = createClient(); +const client = createClient(); - if (process.argv.length !== 3) { - console.log(`usage: node stream-consumer-group.js `); - process.exit(1); - } +if (process.argv.length !== 3) { + console.log(`usage: node stream-consumer-group.js `); + process.exit(1); +} - const consumerName = process.argv[2]; +const consumerName = process.argv[2]; - await client.connect(); +await client.connect(); - // Create the consumer group (and stream) if needed... - try { - await client.xGroupCreate('mystream', 'myconsumergroup', '0', { - MKSTREAM: true - }); - console.log('Created consumer group.'); - } catch (e) { - console.log('Consumer group already exists, skipped creation.'); - } +// Create the consumer group (and stream) if needed... +try { + // https://redis.io/commands/xgroup-create/ + await client.xGroupCreate('mystream', 'myconsumergroup', '0', { + MKSTREAM: true + }); + console.log('Created consumer group.'); +} catch (e) { + console.log('Consumer group already exists, skipped creation.'); +} - console.log(`Starting consumer ${consumerName}.`); +console.log(`Starting consumer ${consumerName}.`); - while (true) { - try { - let response = await client.xReadGroup( - commandOptions({ - isolated: true - }), - 'myconsumergroup', - consumerName, [ - // XREADGROUP can read from multiple streams, starting at a - // different ID for each... - { - key: 'mystream', - id: '>' // Next entry ID that no consumer in this group has read - } - ], { - // Read 1 entry at a time, block for 5 seconds if there are none. - COUNT: 1, - BLOCK: 5000 +while (true) { + try { + // https://redis.io/commands/xreadgroup/ + let response = await client.xReadGroup( + commandOptions({ + isolated: true + }), + 'myconsumergroup', + consumerName, [ + // XREADGROUP can read from multiple streams, starting at a + // different ID for each... + { + key: 'mystream', + id: '>' // Next entry ID that no consumer in this group has read } - ); + ], { + // Read 1 entry at a time, block for 5 seconds if there are none. + COUNT: 1, + BLOCK: 5000 + } + ); - if (response) { - // Response is an array of streams, each containing an array of - // entries: - // - // [ - // { - // "name": "mystream", - // "messages": [ - // { - // "id": "1642088708425-0", - // "message": { - // "num": "999" - // } - // } - // ] - // } - // ] - console.log(JSON.stringify(response)); + if (response) { + // Response is an array of streams, each containing an array of + // entries: + // + // [ + // { + // "name": "mystream", + // "messages": [ + // { + // "id": "1642088708425-0", + // "message": { + // "num": "999" + // } + // } + // ] + // } + // ] + console.log(JSON.stringify(response)); - // Use XACK to acknowledge successful processing of this - // stream entry. - const entryId = response[0].messages[0].id; - await client.xAck('mystream', 'myconsumergroup', entryId); + // Use XACK to acknowledge successful processing of this + // stream entry. + // https://redis.io/commands/xack/ + const entryId = response[0].messages[0].id; + await client.xAck('mystream', 'myconsumergroup', entryId); - console.log(`Acknowledged processing of entry ${entryId}.`); - } else { - // Response is null, we have read everything that is - // in the stream right now... - console.log('No new stream entries.'); - } - } catch (err) { - console.error(err); + console.log(`Acknowledged processing of entry ${entryId}.`); + } else { + // Response is null, we have read everything that is + // in the stream right now... + console.log('No new stream entries.'); } + } catch (err) { + console.error(err); } } - -streamConsumerGroup(); diff --git a/examples/stream-consumer.js b/examples/stream-consumer.js index f6ab16421c..3d5fc20fb4 100644 --- a/examples/stream-consumer.js +++ b/examples/stream-consumer.js @@ -1,64 +1,61 @@ // A sample stream consumer using the blocking variant of XREAD. +// https://redis.io/commands/xread/ // This consumes entries from a stream created by stream-producer.js import { createClient, commandOptions } from 'redis'; -async function streamConsumer() { - const client = createClient(); +const client = createClient(); - await client.connect(); +await client.connect(); - let currentId = '0-0'; // Start at lowest possible stream ID +let currentId = '0-0'; // Start at lowest possible stream ID - while (true) { - try { - let response = await client.xRead( - commandOptions({ - isolated: true - }), [ - // XREAD can read from multiple streams, starting at a - // different ID for each... - { - key: 'mystream', - id: currentId - } - ], { - // Read 1 entry at a time, block for 5 seconds if there are none. - COUNT: 1, - BLOCK: 5000 +while (true) { + try { + let response = await client.xRead( + commandOptions({ + isolated: true + }), [ + // XREAD can read from multiple streams, starting at a + // different ID for each... + { + key: 'mystream', + id: currentId } - ); - - if (response) { - // Response is an array of streams, each containing an array of - // entries: - // [ - // { - // "name": "mystream", - // "messages": [ - // { - // "id": "1642088708425-0", - // "message": { - // "num": "999" - // } - // } - // ] - // } - // ] - console.log(JSON.stringify(response)); - - // Get the ID of the first (only) entry returned. - currentId = response[0].messages[0].id; - console.log(currentId); - } else { - // Response is null, we have read everything that is - // in the stream right now... - console.log('No new stream entries.'); + ], { + // Read 1 entry at a time, block for 5 seconds if there are none. + COUNT: 1, + BLOCK: 5000 } - } catch (err) { - console.error(err); + ); + + if (response) { + // Response is an array of streams, each containing an array of + // entries: + // [ + // { + // "name": "mystream", + // "messages": [ + // { + // "id": "1642088708425-0", + // "message": { + // "num": "999" + // } + // } + // ] + // } + // ] + console.log(JSON.stringify(response)); + + // Get the ID of the first (only) entry returned. + currentId = response[0].messages[0].id; + console.log(currentId); + } else { + // Response is null, we have read everything that is + // in the stream right now... + console.log('No new stream entries.'); } + } catch (err) { + console.error(err); } } - -streamConsumer(); diff --git a/examples/stream-producer.js b/examples/stream-producer.js index 00d6dab7ae..f81931e519 100644 --- a/examples/stream-producer.js +++ b/examples/stream-producer.js @@ -1,53 +1,50 @@ // A sample stream producer using XADD. +// https://redis.io/commands/xadd/ import { createClient } from 'redis'; -async function streamProducer() { - const client = createClient(); - - await client.connect(); - - for (let i = 0; i < 10000; i++) { - await client.xAdd( - 'mystream', - '*', // * = Let Redis generate a timestamp ID for this new entry. - // Payload to add to the stream: - { - i: i.toString() - // Other name/value pairs can go here as required... - } - ); - - // Also add to a stream whose length we will cap at approximately - // 1000 entries using the MAXLEN trimming strategy: - // https://redis.io/commands/xadd/ - - await client.xAdd( - 'mytrimmedstream', - id, // Re-use the ID from the previous stream. - // Payload to add to the stream: - { - i: i.toString() - // Other name/value pairs can go here as required... - }, - // Specify a trimming strategy... - { - TRIM: { - strategy: 'MAXLEN', // Trim by length. - strategyModifier: '~', // Approximate trimming. - threshold: 1000 // Retain around 1000 entries. - } +const client = createClient(); + +await client.connect(); + +for (let i = 0; i < 10000; i++) { + await client.xAdd( + 'mystream', + '*', // * = Let Redis generate a timestamp ID for this new entry. + // Payload to add to the stream: + { + i: i.toString() + // Other name/value pairs can go here as required... + } + ); + + // Also add to a stream whose length we will cap at approximately + // 1000 entries using the MAXLEN trimming strategy: + // https://redis.io/commands/xadd/ + + await client.xAdd( + 'mytrimmedstream', + '*', + // Payload to add to the stream: + { + i: i.toString() + // Other name/value pairs can go here as required... + }, + // Specify a trimming strategy... + { + TRIM: { + strategy: 'MAXLEN', // Trim by length. + strategyModifier: '~', // Approximate trimming. + threshold: 1000 // Retain around 1000 entries. } - ); - } - - // Take a look at how many entries are in the streams... - // Should be 10000: - console.log(`Length of mystream: ${await client.xLen('mystream')}.`); - // Should be approximately 1000: - console.log(`Length of mytrimmedstream: ${await client.xLen('mytrimmedstream')}.`); - - await client.quit(); + } + ); } -streamProducer(); +// Take a look at how many entries are in the streams... +// https://redis.io/commands/xlen/ +// Should be 10000: +console.log(`Length of mystream: ${await client.xLen('mystream')}.`); +// Should be approximately 1000: +console.log(`Length of mytrimmedstream: ${await client.xLen('mytrimmedstream')}.`); +await client.quit(); diff --git a/examples/time-series.js b/examples/time-series.js index 9983a17e74..2f2ac59803 100644 --- a/examples/time-series.js +++ b/examples/time-series.js @@ -1,126 +1,122 @@ // Add data to a Redis TimeSeries and query it. -// Requires the RedisTimeSeries module: https://redistimeseries.io/ +// Requires the RedisTimeSeries module: https://redis.io/docs/stack/timeseries/ import { createClient } from 'redis'; import { TimeSeriesDuplicatePolicies, TimeSeriesEncoding, TimeSeriesAggregationType } from '@redis/time-series'; -async function timeSeries() { - const client = createClient(); - - await client.connect(); - await client.del('mytimeseries'); - - try { - // Create a timeseries - // https://oss.redis.com/redistimeseries/commands/#tscreate - const created = await client.ts.create('mytimeseries', { - RETENTION: 86400000, // 1 day in milliseconds - ENCODING: TimeSeriesEncoding.UNCOMPRESSED, // No compression - DUPLICATE_POLICY: TimeSeriesDuplicatePolicies.BLOCK // No duplicates - }); - - if (created === 'OK') { - console.log('Created timeseries.'); - } else { - console.log('Error creating timeseries :('); - process.exit(1); - } +const client = createClient(); + +await client.connect(); +await client.del('mytimeseries'); + +try { + // Create a timeseries + // https://redis.io/commands/ts.create/ + const created = await client.ts.create('mytimeseries', { + RETENTION: 86400000, // 1 day in milliseconds + ENCODING: TimeSeriesEncoding.UNCOMPRESSED, // No compression + DUPLICATE_POLICY: TimeSeriesDuplicatePolicies.BLOCK // No duplicates + }); + + if (created === 'OK') { + console.log('Created timeseries.'); + } else { + console.log('Error creating timeseries :('); + process.exit(1); + } - let value = Math.floor(Math.random() * 1000) + 1; // Random data point value - let currentTimestamp = 1640995200000; // Jan 1 2022 00:00:00 - let num = 0; + let value = Math.floor(Math.random() * 1000) + 1; // Random data point value + let currentTimestamp = 1640995200000; // Jan 1 2022 00:00:00 + let num = 0; - while (num < 10000) { - // Add a new value to the timeseries, providing our own timestamp: - // https://oss.redis.com/redistimeseries/commands/#tsadd - await client.ts.add('mytimeseries', currentTimestamp, value); - console.log(`Added timestamp ${currentTimestamp}, value ${value}.`); + while (num < 10000) { + // Add a new value to the timeseries, providing our own timestamp: + // https://redis.io/commands/ts.add/ + await client.ts.add('mytimeseries', currentTimestamp, value); + console.log(`Added timestamp ${currentTimestamp}, value ${value}.`); - num += 1; - value = Math.floor(Math.random() * 1000) + 1; // Get another random value - currentTimestamp += 1000; // Move on one second. - } - - // Add multiple values to the timeseries in round trip to the server: - // https://oss.redis.com/redistimeseries/commands/#tsmadd - const response = await client.ts.mAdd([{ - key: 'mytimeseries', - timestamp: currentTimestamp + 60000, - value: Math.floor(Math.random() * 1000) + 1 - }, { - key: 'mytimeseries', - timestamp: currentTimestamp + 120000, - value: Math.floor(Math.random() * 1000) + 1 - }]); - - // response = array of timestamps added by TS.MADD command. - if (response.length === 2) { - console.log('Added 2 entries to timeseries with TS.MADD.'); - } + num += 1; + value = Math.floor(Math.random() * 1000) + 1; // Get another random value + currentTimestamp += 1000; // Move on one second. + } - // Update timeseries retention with TS.ALTER: - // https://oss.redis.com/redistimeseries/commands/#tsalter - const alterResponse = await client.ts.alter('mytimeseries', { - RETENTION: 0 // Keep the entries forever - }); + // Add multiple values to the timeseries in round trip to the server: + // https://redis.io/commands/ts.madd/ + const response = await client.ts.mAdd([{ + key: 'mytimeseries', + timestamp: currentTimestamp + 60000, + value: Math.floor(Math.random() * 1000) + 1 + }, { + key: 'mytimeseries', + timestamp: currentTimestamp + 120000, + value: Math.floor(Math.random() * 1000) + 1 + }]); + + // response = array of timestamps added by TS.MADD command. + if (response.length === 2) { + console.log('Added 2 entries to timeseries with TS.MADD.'); + } - if (alterResponse === 'OK') { - console.log('Timeseries retention settings altered successfully.'); - } + // Update timeseries retention with TS.ALTER: + // https://redis.io/commands/ts.alter/ + const alterResponse = await client.ts.alter('mytimeseries', { + RETENTION: 0 // Keep the entries forever + }); - // Query the timeseries with TS.RANGE: - // https://oss.redis.com/redistimeseries/commands/#tsrangetsrevrange - const fromTimestamp = 1640995200000; // Jan 1 2022 00:00:00 - const toTimestamp = 1640995260000; // Jan 1 2022 00:01:00 - const rangeResponse = await client.ts.range('mytimeseries', fromTimestamp, toTimestamp, { - // Group into 10 second averages. - AGGREGATION: { - type: TimeSeriesAggregationType.AVERAGE, - timeBucket: 10000 - } - }); - - console.log('RANGE RESPONSE:'); - // rangeResponse looks like: - // [ - // { timestamp: 1640995200000, value: 356.8 }, - // { timestamp: 1640995210000, value: 534.8 }, - // { timestamp: 1640995220000, value: 481.3 }, - // { timestamp: 1640995230000, value: 437 }, - // { timestamp: 1640995240000, value: 507.3 }, - // { timestamp: 1640995250000, value: 581.2 }, - // { timestamp: 1640995260000, value: 600 } - // ] - - console.log(rangeResponse); - - // Get some information about the state of the timeseries. - // https://oss.redis.com/redistimeseries/commands/#tsinfo - const tsInfo = await client.ts.info('mytimeseries'); - - // tsInfo looks like this: - // { - // totalSamples: 1440, - // memoryUsage: 28904, - // firstTimestamp: 1641508920000, - // lastTimestamp: 1641595320000, - // retentionTime: 86400000, - // chunkCount: 7, - // chunkSize: 4096, - // chunkType: 'uncompressed', - // duplicatePolicy: 'block', - // labels: [], - // sourceKey: null, - // rules: [] - // } - - console.log('Timeseries info:'); - console.log(tsInfo); - } catch (e) { - console.error(e); + if (alterResponse === 'OK') { + console.log('Timeseries retention settings altered successfully.'); } - await client.quit(); + // Query the timeseries with TS.RANGE: + // https://redis.io/commands/ts.range/ + const fromTimestamp = 1640995200000; // Jan 1 2022 00:00:00 + const toTimestamp = 1640995260000; // Jan 1 2022 00:01:00 + const rangeResponse = await client.ts.range('mytimeseries', fromTimestamp, toTimestamp, { + // Group into 10 second averages. + AGGREGATION: { + type: TimeSeriesAggregationType.AVERAGE, + timeBucket: 10000 + } + }); + + console.log('RANGE RESPONSE:'); + // rangeResponse looks like: + // [ + // { timestamp: 1640995200000, value: 356.8 }, + // { timestamp: 1640995210000, value: 534.8 }, + // { timestamp: 1640995220000, value: 481.3 }, + // { timestamp: 1640995230000, value: 437 }, + // { timestamp: 1640995240000, value: 507.3 }, + // { timestamp: 1640995250000, value: 581.2 }, + // { timestamp: 1640995260000, value: 600 } + // ] + + console.log(rangeResponse); + + // Get some information about the state of the timeseries. + // https://redis.io/commands/ts.info/ + const tsInfo = await client.ts.info('mytimeseries'); + + // tsInfo looks like this: + // { + // totalSamples: 1440, + // memoryUsage: 28904, + // firstTimestamp: 1641508920000, + // lastTimestamp: 1641595320000, + // retentionTime: 86400000, + // chunkCount: 7, + // chunkSize: 4096, + // chunkType: 'uncompressed', + // duplicatePolicy: 'block', + // labels: [], + // sourceKey: null, + // rules: [] + // } + + console.log('Timeseries info:'); + console.log(tsInfo); +} catch (e) { + console.error(e); } -timeSeries(); +await client.quit(); diff --git a/examples/topk.js b/examples/topk.js index 024dc30ecb..35cdc4a850 100644 --- a/examples/topk.js +++ b/examples/topk.js @@ -1,112 +1,113 @@ // This example demonstrates the use of the Top K -// in the RedisBloom module (https://redisbloom.io/) +// in the RedisBloom module (https://redis.io/docs/stack/bloom/) import { createClient } from 'redis'; -async function topK() { - const client = createClient(); +const client = createClient(); - await client.connect(); +await client.connect(); - // Delete any pre-existing Top K. - await client.del('mytopk'); +// Delete any pre-existing Top K. +await client.del('mytopk'); - // Reserve a Top K to track the 10 most common items. - // https://oss.redis.com/redisbloom/TopK_Commands/#topkreserve - try { - await client.topK.reserve('mytopk', 10); - console.log('Reserved Top K.'); - } catch (e) { - if (e.message.endsWith('key already exists')) { - console.log('Top K already reserved.'); - } else { - console.log('Error, maybe RedisBloom is not installed?:'); - console.log(e); - } +// Reserve a Top K to track the 10 most common items. +// https://redis.io/commands/topk.reserve/ +try { + await client.topK.reserve('mytopk', 10, { width: 400, depth: 10, decay: 0.9 }); + console.log('Reserved Top K.'); +} catch (e) { + if (e.message.endsWith('key already exists')) { + console.log('Top K already reserved.'); + } else { + console.log('Error, maybe RedisBloom is not installed?:'); + console.log(e); } +} - const teamMembers = [ - 'leibale', - 'simon', - 'guy', - 'suze', - 'brian', - 'steve', - 'kyleb', - 'kyleo', - 'josefin', - 'alex', - 'nava', - 'lance', - 'rachel', - 'kaitlyn' - ]; +const teamMembers = [ + 'leibale', + 'simon', + 'guy', + 'suze', + 'brian', + 'steve', + 'kyleb', + 'kyleo', + 'josefin', + 'alex', + 'nava', + 'lance', + 'rachel', + 'kaitlyn' +]; - // Add random counts for random team members with TOPK.INCRBY - for (let n = 0; n < 1000; n++) { - const teamMember = teamMembers[Math.floor(Math.random() * teamMembers.length)]; - const points = Math.floor(Math.random() * 1000) + 1; - await client.topK.incrBy('mytopk', { - item: teamMember, - incrementBy: points - }); - console.log(`Added ${points} points for ${teamMember}.`); - } +// Add random counts for random team members with TOPK.INCRBY +// https://redis.io/commands/topk.incrby/ +for (let n = 0; n < 1000; n++) { + const teamMember = teamMembers[Math.floor(Math.random() * teamMembers.length)]; + const points = Math.floor(Math.random() * 1000) + 1; + await client.topK.incrBy('mytopk', { + item: teamMember, + incrementBy: points + }); + console.log(`Added ${points} points for ${teamMember}.`); +} - // List out the top 10 with TOPK.LIST - const top10 = await client.topK.list('mytopk'); - console.log('The top 10:'); - // top10 looks like this: - // [ - // 'guy', 'nava', - // 'kaitlyn', 'brian', - // 'simon', 'suze', - // 'lance', 'alex', - // 'steve', 'kyleo' - // ] - console.log(top10); +// List out the top 10 with TOPK.LIST +// https://redis.io/commands/topk.list/ +const top10 = await client.topK.list('mytopk'); +console.log('The top 10:'); +// top10 looks like this: +// [ +// 'guy', 'nava', +// 'kaitlyn', 'brian', +// 'simon', 'suze', +// 'lance', 'alex', +// 'steve', 'kyleo' +// ] +console.log(top10); - // List out the top 10 with their counts (requires RedisBloom >=2.2.9) - const top10WithCounts = await client.topK.listWithCount('mytopk'); - console.log('The top 10 with counts:'); - console.log(top10WithCounts); - // top10WithCounts looks like this: - // [ - // { item: 'suze', count: 42363 }, - // { item: 'lance', count: 41982 }, - // { item: 'simon', count: 41831 }, - // { item: 'steve', count: 39237 }, - // { item: 'guy', count: 39078 }, - // { item: 'kyleb', count: 37338 }, - // { item: 'leibale', count: 34230 }, - // { item: 'kyleo', count: 33812 }, - // { item: 'alex', count: 33679 }, - // { item: 'nava', count: 32663 } - // ] +// List out the top 10 with their counts (requires RedisBloom >=2.2.9) +// https://redis.io/commands/topk.list/ +const top10WithCounts = await client.topK.listWithCount('mytopk'); +console.log('The top 10 with counts:'); +console.log(top10WithCounts); +// top10WithCounts looks like this: +// [ +// { item: 'suze', count: 42363 }, +// { item: 'lance', count: 41982 }, +// { item: 'simon', count: 41831 }, +// { item: 'steve', count: 39237 }, +// { item: 'guy', count: 39078 }, +// { item: 'kyleb', count: 37338 }, +// { item: 'leibale', count: 34230 }, +// { item: 'kyleo', count: 33812 }, +// { item: 'alex', count: 33679 }, +// { item: 'nava', count: 32663 } +// ] - // Check if a few team members are in the top 10 with TOPK.QUERY: - const [ steve, suze, leibale, frederick ] = await client.topK.query('mytopk', [ - 'steve', - 'suze', - 'leibale', - 'frederick' - ]); +// Check if a few team members are in the top 10 with TOPK.QUERY: +// https://redis.io/commands/topk.query/ +const [ steve, suze, leibale, frederick ] = await client.topK.query('mytopk', [ + 'steve', + 'suze', + 'leibale', + 'frederick' +]); - console.log(`steve ${steve === 1 ? 'is': 'is not'} in the top 10.`); - console.log(`suze ${suze === 1 ? 'is': 'is not'} in the top 10.`); - console.log(`leibale ${leibale === 1 ? 'is': 'is not'} in the top 10.`); - console.log(`frederick ${frederick === 1 ? 'is': 'is not'} in the top 10.`); +console.log(`steve ${steve === 1 ? 'is': 'is not'} in the top 10.`); +console.log(`suze ${suze === 1 ? 'is': 'is not'} in the top 10.`); +console.log(`leibale ${leibale === 1 ? 'is': 'is not'} in the top 10.`); +console.log(`frederick ${frederick === 1 ? 'is': 'is not'} in the top 10.`); - // Get count estimate for some team members: - const [ simonCount, lanceCount ] = await client.topK.count('mytopk', [ - 'simon', - 'lance' - ]); +// Get count estimate for some team members with TOPK.COUNT: +// https://redis.io/commands/topk.count/ +const [ simonCount, lanceCount ] = await client.topK.count('mytopk', [ + 'simon', + 'lance' +]); - console.log(`Count estimate for simon: ${simonCount}.`); - console.log(`Count estimate for lance: ${lanceCount}.`); - - await client.quit(); -} +console.log(`Count estimate for simon: ${simonCount}.`); +console.log(`Count estimate for lance: ${lanceCount}.`); -topK(); +await client.quit();