{"_id":"@emmanuelnk/redis-time-series-ts","_rev":"2-b4b92b8222a4f92b33495c3cb0ddf2c3","name":"@emmanuelnk/redis-time-series-ts","dist-tags":{"latest":"1.0.1"},"versions":{"1.0.0":{"name":"@emmanuelnk/redis-time-series-ts","version":"1.0.0","description":"Typescript RedisTimeSeries client","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest -i --config jest.config.js --coverage","test:watch":"jest -i --config jest.config.js --coverage --watchAll","build":"tsc","format":"prettier --write \"src/**/*.ts\" \"src/**/*.js\"","lint":"eslint \"src/**\"","prepare":"npm run build","prepublishOnly":"npm test && npm run lint","preversion":"npm run lint","version":"npm run format && git add -A src","postversion":"git push && git push --tags"},"repository":{"type":"git","url":"git+https://github.com/emmanuelnk/redis-time-series.git"},"keywords":["redis","redistimeseries","redislabs","timeseries","javascript","typescript"],"author":{"name":"Emmanuel Kyeyune"},"license":"MIT","homepage":"https://github.com/emmanuelnk/redis-time-series","dependencies":{"ioredis":"^4.19.4"},"devDependencies":{"@types/ioredis":"^4.17.10","@types/jest":"^24.9.1","@types/node":"^12.19.11","@typescript-eslint/eslint-plugin":"^2.34.0","@typescript-eslint/parser":"^2.34.0","eslint":"^6.8.0","eslint-config-prettier":"^6.15.0","eslint-plugin-prettier":"^3.3.0","jest":"^25.5.4","prettier":"^1.19.1","ts-jest":"^25.5.1","typescript":"^3.9.7"},"gitHead":"03af58672cbe362c9c48bce4fb573048bf720c4a","bugs":{"url":"https://github.com/emmanuelnk/redis-time-series/issues"},"_id":"@emmanuelnk/redis-time-series-ts@1.0.0","_nodeVersion":"14.15.1","_npmVersion":"6.14.8","dist":{"integrity":"sha512-EtfJOkRwrpJynXPwQ74IZoGi2jP8dw55e22pHGh3xngFFSQGAMvPzp/ZQTUfK5TwQFjETLgSysMAcdLOXj8x3Q==","shasum":"02044d010e8818f6ac87012899a42843c9fdc74d","tarball":"https://registry.npmjs.org/@emmanuelnk/redis-time-series-ts/-/redis-time-series-ts-1.0.0.tgz","fileCount":112,"unpackedSize":113021,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJf7Wk2CRA9TVsSAnZWagAAnZ0P/2Q1UwJfAFmiJHRLbozg\na1IyKuFgL2Nk0EFeTT6b674KFz0R4/K6hwXvi/oxachBNIX9XQ7BqrQGdy6n\nUiOW5jDM3MQ5o6J+7cFRnQ1wkhu0mYVh4YOjTXMRLxYFmI8jQ23+R/MWmFcq\nzSBII30h4pbSDhIusvr+HtJIR/t/2EUhhNs5nUCo7o1Yu8ixoZ5LcwZjiAQP\npFjnYTh/1Ia46PXqxl7weDfdztlG6odCNHL1WXCkw89ZHbYP/xTJI5b39AK3\nZ85rdq0zZH+RKy29ew3C5s6nbguUco/SYOOqJgBhJ7Npas4AwHZph5GRZ2ax\n0PmeJ+5Vzu8LAyXJcnACHwkmxJ1c3Ua2ZcvFnXaolWINRqwRtrXTn9r0UoPo\nEPpKeUyjH+KPtZXmCS7ybejHz9gpEFKZitDlQWVqEMZIO5T5tsoGhiwbRq4Q\nWmQIL9veRdd3PF7U09CF7FlxG5glUSw7Ks8JkrD0AOHh6xM/szCSTLgqlwBK\n5JJGfe/I+NzmNqa3ymYrgNeWt4BFZvI44RwDLuazx0HmrK4HkYppOEu14e0r\nFYeesusNC061P/f1KmuE46FgxxmQL38lnlYJFkgOmIwqd7OeZ1/dgeji7kp+\nOlTbITme4kAUtzLKudHmTmvY1pIBGxFSgYS5WgIZ+/fIuStjHI8tEEHfBhrR\negHl\r\n=VHT7\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDeIsmJ4gIJAQoWBmBtIDR6MazxgMXkHD3o294LIMdyFAIgEQY3OncT75fD7hoY4D2c1VosoOtgQS0P653EsS8C63c="}]},"_npmUser":{"name":"emmanuelnk","email":"emmakyeyune@gmail.com"},"directories":{},"maintainers":[{"name":"emmanuelnk","email":"emmakyeyune@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/redis-time-series-ts_1.0.0_1609394485666_0.4763397493924886"},"_hasShrinkwrap":false},"1.0.1":{"name":"@emmanuelnk/redis-time-series-ts","version":"1.0.1","description":"Javascript RedisTimeSeries client","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"test":"jest -i --config jest.config.js --coverage","test:watch":"jest -i --config jest.config.js --coverage --watchAll","build":"tsc","format":"prettier --write \"src/**/*.ts\" \"src/**/*.js\"","lint":"eslint \"src/**\"","prepare":"npm run build","prepublishOnly":"npm test && npm run lint","preversion":"npm run lint","version":"npm run format && git add -A src","postversion":"git push && git push --tags"},"repository":{"type":"git","url":"git+https://github.com/emmanuelnk/redis-time-series.git"},"keywords":["redis","redistimeseries","redislabs","timeseries","javascript","typescript"],"author":{"name":"Emmanuel N K"},"license":"MIT","homepage":"https://github.com/emmanuelnk/redis-time-series","dependencies":{"ioredis":"^4.19.4"},"devDependencies":{"@types/ioredis":"^4.17.10","@types/jest":"^24.9.1","@types/node":"^12.19.11","@typescript-eslint/eslint-plugin":"^2.34.0","@typescript-eslint/parser":"^2.34.0","eslint":"^6.8.0","eslint-config-prettier":"^6.15.0","eslint-plugin-prettier":"^3.3.0","jest":"^25.5.4","prettier":"^1.19.1","ts-jest":"^25.5.1","typescript":"^3.9.7"},"gitHead":"c04af88c35d9effbc91e78d5afbb26efe704f482","bugs":{"url":"https://github.com/emmanuelnk/redis-time-series/issues"},"_id":"@emmanuelnk/redis-time-series-ts@1.0.1","_nodeVersion":"14.15.1","_npmVersion":"6.14.8","dist":{"integrity":"sha512-AhhC6ILCas4IE/uX9NCO7LvYNG2GUv/zSU6MEjcPtnv+Cv2p2VYg7E6LKPWZbg/LKXmwRuzoFjXczzZmf3pIBA==","shasum":"822d8ae0cdb309226155694bfff1eb4744c18121","tarball":"https://registry.npmjs.org/@emmanuelnk/redis-time-series-ts/-/redis-time-series-ts-1.0.1.tgz","fileCount":115,"unpackedSize":173618,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJf8959CRA9TVsSAnZWagAAx0QP/jfPG+ec22yrD/TJVErK\nUZGPlmRVhTt6/JJ/CqvxmcoJy1l0Fwp+yyqemi5ExE/HJJQyqzBvoSzHHUYm\nRky1KAqiq38BpOv/8Fgz7JYnh6hq0Eyd0UlVlzWQ8xni7OjnJ3s9OJstjQSi\nPZTC8v+q+I0hUlcwJglmGorODkq9l8E8b66zrriYoUJ/q/2p1WFPzNWjDHYL\nwwYIUNzVvOUP69KIJXZkAJkZ4TKYE8cp3s5B3g4+eF7TlzmOHJBSibMT2j7W\nWGW6cdcByLaL15lScxG4x0EOAMrNGM5pxXW1+auHOxZZD6cVOQ954zEDg9mS\n8o57o+SM5WDq5q5Sy8L94av/jO7Yp6R65EL+qRInxbJB46xRNehO5TERfROu\nMwOanjW8ZBRVBaH5ZYU26vg2ctk8MGkeLrSiymJZ/LssOU7xCkOgEJPd0x4L\n8k0U0ZwK46rVCgSemVKDtIK3mMZXBy2T2edaadBT/G0129TO9zp2y7QhsVbu\nikomfoHyaLArE2nRkqR1Q0m1zqiln8xAwrjLiWXbn8Ar61k1HMs8B1D7RgwN\n/Pr200etJzJ0fhgWcc6kCTN975WZ6gBpErPEXQGAvua2TelFz3DPnDuRhmQn\nEZJ5b87aEBjoeNCbx1DNc4u65nyrpK/xFW4bwAj4Fzn8kot1ZKr0URKCcMMs\nxvDU\r\n=eQvT\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDSwT9BCdyQoNWashJCy1s1FKFAvznW7F6TRPeYIqdWJAIgF9YFaDs+IeE/evt9nUlukzX5dsNyi+4iQj1whcpcsZI="}]},"_npmUser":{"name":"emmanuelnk","email":"emmakyeyune@gmail.com"},"directories":{},"maintainers":[{"name":"emmanuelnk","email":"emmakyeyune@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/redis-time-series-ts_1.0.1_1609817724568_0.21896084065777832"},"_hasShrinkwrap":false}},"time":{"created":"2020-12-31T06:01:25.606Z","1.0.0":"2020-12-31T06:01:25.895Z","modified":"2022-04-05T07:34:07.049Z","1.0.1":"2021-01-05T03:35:24.745Z"},"maintainers":[{"name":"emmanuelnk","email":"emmakyeyune@gmail.com"}],"description":"Javascript RedisTimeSeries client","homepage":"https://github.com/emmanuelnk/redis-time-series","keywords":["redis","redistimeseries","redislabs","timeseries","javascript","typescript"],"repository":{"type":"git","url":"git+https://github.com/emmanuelnk/redis-time-series.git"},"author":{"name":"Emmanuel N K"},"bugs":{"url":"https://github.com/emmanuelnk/redis-time-series/issues"},"license":"MIT","readme":"[![Test Coverage](https://api.codeclimate.com/v1/badges/f178828dd4e2cbaa32c5/test_coverage)](https://codeclimate.com/github/averias/redis-time-series/test_coverage)\n[![Maintainability](https://api.codeclimate.com/v1/badges/f178828dd4e2cbaa32c5/maintainability)](https://codeclimate.com/github/averias/redis-time-series/maintainability)\n[![Build Status](https://travis-ci.org/averias/redis-time-series.svg?branch=master)](https://travis-ci.org/averias/redis-time-series)\n[![npm version](https://badge.fury.io/js/redis-time-series-ts.svg)](https://badge.fury.io/js/@emmanuelnk/redis-time-series-ts)\n[![GitHub](https://img.shields.io/github/license/averias/redis-time-series.svg)](https://github.com/averias/redis-time-series)\n\n# Redis-Time-Series\nA Javascript client for [RedisLab/RedisTimeSeries Module](https://oss.redislabs.com/redistimeseries/) implemented in \nTypeScript and based on [ioredis](https://github.com/luin/ioredis). This is a fork of [averias/redis-time-series](https://github.com/averias/redis-time-series).\n\n- [Redis-Time-Series](#redis-time-series)\n  - [Requirements](#requirements)\n  - [Install](#install)\n  - [Usage](#usage)\n  - [Commands](#commands)\n    - [`.create`](#create)\n    - [`.alter`](#alter)\n    - [`.add`](#add)\n    - [`.multiAdd`](#multiadd)\n    - [`.incrementBy/.decrementBy`](#incrementbydecrementby)\n    - [`.createRule/.deleteRule`](#createruledeleterule)\n    - [`.range/.revRange`](#rangerevrange)\n    - [`.multiRange/multiRevRange`](#multirangemultirevrange)\n    - [`.get`](#get)\n    - [`.multiGet`](#multiget)\n    - [`.queryIndex`](#queryindex)\n    - [`.info`](#info)\n    - [`.expire`](#expire)\n    - [`.delete`](#delete)\n    - [`.deleteAll`](#deleteall)\n    - [`.reset`](#reset)\n    - [`.disconnect`](#disconnect)\n  - [Testing](#testing)\n  - [License](#license)\n\n## Requirements\n- Redis server 4.0+ version (recommended version 5.0+)\n- RedisTimeSeries Module installed on Redis server as specified in [Build and Run it yourself](https://oss.redislabs.com/redistimeseries/#build-and-run-it-yourself)\n\n\n## Install\n`npm i @emmanuelnk/redis-time-series-ts`\n\n\n## Usage\n\n```ts\nimport { \n    Label, \n    RedisTimeSeriesFactory \n} from \"@emmanuelnk/redis-time-series-ts\";\n\nconst example = async () => {\n    const factory = new RedisTimeSeriesFactory();\n    const redisTimeSeries = factory.create();\n\n    await redisTimeSeries.create(\"temperature\", [new Label(\"sensor\", 1)], 50000);\n\n    const info = await redisTimeSeries.info(\"temperature\");\n    const label = info.labels.shift();\n\n    if (label != null) {\n        console.log(`label: ${label.getName()}=${label.getValue()}`); // label: sensor=1\n    }\n\n    console.log(`retention (ms): ${info.retentionTime}`); // retention (ms): 50000\n    console.log(`last timestamp: ${info.lastTimestamp}`); // last timestamp: 0\n\n    await redisTimeSeries.disconnect();\n};\n\nexample();\n```\n\nIf no param is provided to `RedisTimeSeries` constructor, it creates `RedsiTimeSeries` object with a default \nconnection (port: 6379, host: \"127.0.0.1\" and database: 15). You can specify your connection params by providing an \nobject of `ConnectionOptions` type (an IORedis `RedisOptions` type) which will overwrite those default connection params:\n\n```ts\nimport { \n    ConnectionOptions, \n    RedisTimeSeriesFactory \n} from \"@emmanuelnk/redis-time-series-ts\";\n\nconst options: ConnectionOptions = {\n    port: 6381,\n    host: \"127.0.0.1\",\n    db: 15\n};\n\nconst factory = new RedisTimeSeriesFactory(options);\nconst redisTimeSeries = factory.create();\n```\n\nTake a look at the full [list of connections params](https://github.com/luin/ioredis/blob/master/API.md#new-redisport-host-options) \nfor IORedis.\n\n## Commands\nAfter creating a `RedisTimeSeries` from `RedisTimeSeries::create` you can issue the following async commands. All of them return a `Promise` if the command was executed successfully, otherwise, an `Error` will be thrown.\n\n\n### `.create`\nCreates a new time-series with an optional array of labels and optional retention. If the time-series `key` already\nexists, an `Error` will be thrown.\n\n```ts\nredisTimeSeries.create(\n    key: string, \n    labels?: Label[], \n    retention?: number, \n    chunkSize?: number,\n    duplicatePolicy?: string,\n    uncompressed?: boolean\n): Promise<boolean>\n```\n- `retention` -  Maximum age for samples compared to last event time (in milliseconds). Default: The global retention secs configuration of the database (by default, 0 )\nWhen set to 0, the series is not trimmed at all\n- `chunkSize` - amount of memory, in bytes, allocated for data. Default: 4000.\n- `duplicatePolicy` configures what to do on encounterimg duplicate samples. When this is not set, the server-wide default will be used. See [DUPLICATE_POLICY](https://oss.redislabs.com/redistimeseries/configuration/#DUPLICATE_POLICY) for allowed values.\n- `uncompressed` By default, data are compressed in a time-series, you can revert this behavior by setting `uncompressed` to true\n\n**Label**\n\nIt represents metadata labels of the time-series\n\n`Label(name: string, value: string | number)`\n\n**Response**\n\nTrue if the time-series was created, otherwise false\n\n**Example**\n\n```ts\nimport { \n    Label, \n    RedisTimeSeriesFactory \n} from \"@emmanuelnk/redis-time-series-ts\";\n\nconst example = async () => {\n    const factory = new RedisTimeSeriesFactory();\n    const redisTimeSeries = factory.create();\n\n    const created = await redisTimeSeries.create(\"temperature\", [new Label(\"sensor\", 1)], 50000);\n    console.log(created); // true\n\n    const info = await redisTimeSeries.info(\"temperature\");\n    const label = info.labels.shift();\n\n    if (label != null) {\n        console.log(`label: ${label.getName()}=${label.getValue()}`); // label: sensor=1\n    }\n\n    await redisTimeSeries.disconnect();\n};\n\nexample();\n```\n\nMore info: [TS.CREATE](https://oss.redislabs.com/redistimeseries/commands/#tscreate)\n\n### `.alter`\nUpdates the retention and labels of an existing time-series. Same params as `create`.\n\n```ts\nredisTimeSeries.alter(    \n    key: string, \n    labels?: Label[], \n    retention?: number, \n    chunkSize?: number,\n    duplicatePolicy?: string,\n    uncompressed?: boolean\n): Promise<boolean>\n```\n\n- if time-series key doesn't exist an `Error` is thrown\n- only provided params will be updated\n- to remove all labels from an existing time-series, you must provide and empty Labels array\n\n**Response**\n\nTrue if the time-series was altered, otherwise false\n\n**Example**\n\n```ts\nimport { \n    Label, \n    RedisTimeSeriesFactory \n} from \"@emmanuelnk/redis-time-series-ts\";\n\nconst example = async () => {\n    const factory = new RedisTimeSeriesFactory({ port: 6381, db: 15 });\n    const redisTimeSeries = factory.create();\n\n    await redisTimeSeries.create(\"temperature\", [new Label(\"sensor\", 1)], 50000);\n\n    const infoCreate = await redisTimeSeries.info(\"temperature\");\n    const labelCreate = infoCreate.labels.shift();\n\n    if (labelCreate != null) {\n        console.log(`label: ${labelCreate.getName()}=${labelCreate.getValue()}`); // label: sensor=1\n    }\n\n    console.log(`retention (ms): ${infoCreate.retentionTime}`); // retention (ms): 50000\n\n    // labels are removed and retention is updated to 70000\n    const altered = await redisTimeSeries.alter(\"temperature\", [], 70000);\n    console.log(altered); // true\n\n    const infoAltered = await redisTimeSeries.info(\"temperature\");\n    const labelAltered = infoAltered.labels.shift();\n\n    if (labelAltered != null) {\n        // never executed since we removed labels\n        console.log(`label: ${labelAltered.getName()}=${labelAltered.getValue()}`);\n    }\n\n    console.log(`retention (ms): ${infoAltered.retentionTime}`); // retention (ms): 70000\n\n    await redisTimeSeries.delete(\"temperature\");\n    await redisTimeSeries.disconnect();\n};\n\nexample();\n```\n\nMore info: [TS.ALTER](https://oss.redislabs.com/redistimeseries/commands/#tsalter)\n\n### `.add`\nAppends, or first creates a time-series and then appends, a new value to the time-series.\n\n```ts\nredisTimeSeries.add(\n    sample: Sample, \n    labels?: Label[], \n    retention?: number,\n    chunkSize?: number,\n    onDuplicate?: string,\n    uncompressed?: boolean\n): Promise<number>\n```\n\nIf this command is used to add data to an existing time-series, retentionTime and labels are ignored.\n\n**Sample**\n\nA sample represents the new value to be added where:\n- `key`: is the time-series and\n- `value`: the value to add\n- `timestamp`: (optional) if it's provided, must be a valid timestamp and no older than the last one added. If it's omitted, it will store a string value `*`, which represents a current timestamp in Redis server\n\n`Sample(key: string, value: number, timestamp?: number)`\n\n**Response**\n\nThe timestamp value of the sample added\n\n**Example**\n\n```ts\nimport { \n    Label, \n    Sample, \n    RedisTimeSeriesFactory \n} from \"@emmanuelnk/redis-time-series-ts\";\n\nconst example = async () => {\n    const factory = new RedisTimeSeriesFactory({ port: 6381, db: 15 });\n    const redisTimeSeries = factory.create();\n    const date = Date.now();\n\n    let added = await redisTimeSeries.add(\n        new Sample(\"temperature\", 100, date - 10000),\n        [new Label(\"sensor\", 1)],\n        50000\n    );\n    console.log(added); // date - 10000\n\n    let info = await redisTimeSeries.info(\"temperature\");\n    let label = info.labels.shift();\n\n    if (label != null) {\n        console.log(`label: ${label.getName()}=${label.getValue()}`); // label: sensor=1\n    }\n\n    console.log(`retention (ms): ${info.retentionTime}`); // retention (ms): 50000\n\n    let sample = await redisTimeSeries.get(\"temperature\");\n    console.log(`${sample.getKey()}`); // temperature\n    console.log(`${sample.getValue()}`); // 100\n    console.log(`${sample.getTimestamp()}`); // date - 10000\n\n    // a new value is added, labels and retention are ignored since we added them previously\n    added = await redisTimeSeries.add(\n        new Sample(\"temperature\", 500, date - 5000),\n        [new Label(\"sensor\", 2)],\n        70000\n    );\n    console.log(added); // date - 5000\n\n    info = await redisTimeSeries.info(\"temperature\");\n    label = info.labels.shift();\n\n    if (label != null) {\n        console.log(`label: ${label.getName()}=${label.getValue()}`); // still  sensor=1\n    }\n\n    console.log(`retention (ms): ${info.retentionTime}`); // still retention (ms): 50000\n\n    sample = await redisTimeSeries.get(\"temperature\");\n    console.log(`${sample.getKey()}`); // temperature\n    console.log(`${sample.getValue()}`); // 500\n    console.log(`${sample.getTimestamp()}`); // date - 5000\n\n    await redisTimeSeries.delete(\"temperature\");\n    await redisTimeSeries.disconnect();\n};\n\nexample();\n```\n\nMore info: [TS.ADD](https://oss.redislabs.com/redistimeseries/commands/#tsadd)\n\n### `.multiAdd`\nSimilar to `Add` but it appends a list of new values to a time-series, the `key` specified in each sample must exist.\n\n`redisTimeSeries.multiAdd(samples: Sample[]): Promise<(number | MultiAddResponseError)[]>`\n\n**Response**\n\nIt returns an array of integers for each value added which is the timestamp specified in the sample, following the order \nthe samples were added. If an error happens when the sample is added, instead of an integer and object of type `MultiAddResponseError`\nwill be returned:\n\n```\ntype MultiAddResponseError = {\n    stack: string;\n    message: string;\n};\n``` \n\n**Example**\n\n```ts\nimport { \n    Label, \n    Sample, \n    FilterBuilder, \n    RedisTimeSeriesFactory \n} from \"@emmanuelnk/redis-time-series-ts\";\n\nconst example = async () => {\n    const factory = new RedisTimeSeriesFactory({ port: 6381, db: 15 });\n    const redisTimeSeries = factory.create();\n    const date = Date.now();\n    const label = new Label(\"sensor\", 1);\n    const sample1 = new Sample(\"temperature1\", 100, date - 10000);\n    const sample2 = new Sample(\"temperature2\", 200, date - 5000);\n\n    await redisTimeSeries.create(\"temperature1\", [label]);\n    await redisTimeSeries.create(\"temperature2\", [label]);\n\n    const multiAdded = await redisTimeSeries.multiAdd([sample1, sample2]);\n    console.log(multiAdded[0]); // date - 10000\n    console.log(multiAdded[1]); // date - 5000\n\n    const multiGet = await redisTimeSeries.multiGet(new FilterBuilder(\"sensor\", 1));\n    const temperature1 = multiGet[0];\n    const temperature2 = multiGet[1];\n\n    console.log(`${temperature1.data.getKey()}`); // temperature1\n    console.log(`${temperature1.data.getValue()}`); // 100\n    console.log(`${temperature1.data.getTimestamp()}`); // date - 10000\n\n    console.log(`${temperature2.data.getKey()}`); // temperature2\n    console.log(`${temperature2.data.getValue()}`); // 200\n    console.log(`${temperature2.data.getTimestamp()}`); // date - 5000\n\n    await redisTimeSeries.delete(\"temperature1\", \"temperature2\");\n    await redisTimeSeries.disconnect();\n};\n\nexample();\n```\n\nMore info: [TS.MADD](https://oss.redislabs.com/redistimeseries/commands/#tsmadd)\n\n\n### `.incrementBy/.decrementBy`\nIncrement or decrement the latest value in a time-series\n\n`redisTimeSeries.incrementBy(sample: Sample, labels?: Label[], retention?: number, uncompressed?: boolean): Promise<number>`\n\n`redisTimeSeries.decrementBy(sample: Sample, labels?: Label[], retention?: number, uncompressed?: boolean): Promise<number>`\n\nYou can use these command to add data to an non existing time-series, then `labels` and `retention` are ignored. By default, \ndata are compressed in a time-series, you can revert this behavior by setting `uncompressed` to true\n\n**Response**\n\nThe timestamp value of the sample incremented/decremented\n\n**Example**\n\n```ts\nimport { \n    Label, \n    Sample, \n    RedisTimeSeriesFactory \n} from \"@emmanuelnk/redis-time-series-ts\";\n\nconst example = async () => {\n    const factory = new RedisTimeSeriesFactory({ port: 6381, db: 15 });\n    const redisTimeSeries = factory.create();\n    const date = Date.now();\n    const label = new Label(\"sensor\", 1);\n    const sample1 = new Sample(\"temperature\", 100, date - 10000);\n    const sample2 = new Sample(\"temperature\", 200, date - 5000);\n\n    const increment = await redisTimeSeries.incrementBy(sample1, [label]);\n    console.log(increment); // date - 10000\n\n    let temperature = await redisTimeSeries.get(\"temperature\");\n\n    console.log(`${temperature.getKey()}`); // temperature\n    console.log(`${temperature.getValue()}`); // 100\n    console.log(`${temperature.getTimestamp()}`); // date - 10000\n\n    const decrement = await redisTimeSeries.decrementBy(sample2, [label]);\n    console.log(decrement); // date - 5000\n\n    temperature = await redisTimeSeries.get(\"temperature\");\n\n    console.log(`${temperature.getKey()}`); // temperature\n    console.log(`${temperature.getValue()}`); // -100\n    console.log(`${temperature.getTimestamp()}`); // date - 5000\n\n    await redisTimeSeries.delete(\"temperature\");\n    await redisTimeSeries.disconnect();\n};\n\nexample();\n```\n\nMore info: [TS.INCRBY / TS.DECRBY](https://oss.redislabs.com/redistimeseries/commands/#tsincrbytsdecrby)\n\n### `.createRule/.deleteRule`\nit creates a compaction rule.\n\n`redisTimeSeries.createRule(sourceKey: string, destKey: string, aggregation: Aggregation): Promise<boolean>`\n\nDeletes a previous compaction rule.\n\n`redisTimeSeries.deleteRule(sourceKey: string, destKey: string): Promise<boolean>`\n\nSource and destination key must exist and be different\n\n**Aggregation**\n\nA aggregation represents a rule:\n- `aggregationType`: avg, sum, min, max, range, count, first, last, std.p, std.s, var.p and var.s. See `AggregationType` enum\n- `timeBucket`: a positive integer time bucket in milliseconds\n\n`Aggregation(type: string, timeBucketInMs: number)`\n\n**Response**\n\nTrue if the aggregation rule was created/deleted, otherwise false\n\n**Example**\n\n```ts\nimport { \n    Aggregation, \n    AggregationType, \n    RedisTimeSeriesFactory \n} from \"@emmanuelnk/redis-time-series-ts\";\n\nconst example = async () => {\n    const factory = new RedisTimeSeriesFactory({ port: 6381, db: 15 });\n    const redisTimeSeries = factory.create();\n\n    await redisTimeSeries.create(\"rule1\");\n    await redisTimeSeries.create(\"rule2\");\n\n    const aggregation = new Aggregation(AggregationType.AVG, 50000);\n    const ruled = await redisTimeSeries.createRule(\"rule1\", \"rule2\", aggregation);\n    console.log(ruled); // true\n\n    let info1 = await redisTimeSeries.info(\"rule1\");\n    console.log(info1.rules.rule2.getTimeBucketInMs()); // 50000\n    console.log(info1.rules.rule2.getType()); // avg\n\n    let info2 = await redisTimeSeries.info(\"rule2\");\n    console.log(info2.sourceKey); // rule1\n\n    const deleted = await redisTimeSeries.deleteRule(\"rule1\", \"rule2\");\n    console.log(deleted); // true\n\n    info1 = await redisTimeSeries.info(\"rule1\");\n    console.log(info1.rules); // {}}\n\n    info2 = await redisTimeSeries.info(\"rule2\");\n    console.log(info2.sourceKey); // undefined\n\n    await redisTimeSeries.delete(\"rule1\", \"rule2\");\n    await redisTimeSeries.disconnect();\n};\n\nexample();\n```\n\nMore info: \n- [TS.CREATERULE](https://oss.redislabs.com/redistimeseries/commands/#tscreaterule)\n- [TS.DELETERULE](https://oss.redislabs.com/redistimeseries/commands/#tsdeleterule)\n\n### `.range/.revRange`\nIt queries a timestamp range.\n\n`redisTimeSeries.range(key: string, range: TimestampRange, count?: number, aggregation?: Aggregation): Promise<Array<Sample>>`\n\n- `range`: a `TimestampRange` object\n- `count`: (optional) maximum number of returned samples per time-series\n- `aggregation`: (optional) aggregation rule\n\n\n**TimestampRange**\n\nIt represents a timestamp filter for the query:\n- `from`: (optional) start timestamp value, if it's not specified or `undefined` represents the minimum possible timestamp (0)\n- `to`: (optional) end timestamp value, if it's not specified or `undefined` represents the maximum possible timestamp (current timestamp in the Redis server)\n\n`TimestampRange(from?: number, to?: number)`\n\n\n**Response**\n\nAn array of samples which represent all the samples included in the query\n\n**Example**\n\n```ts\nimport { \n    TimestampRange, \n    AggregationType, \n    Aggregation, \n    Sample, \n    RedisTimeSeriesFactory \n} from \"@emmanuelnk/redis-time-series-ts\";\n\nconst example = async () => {\n    const factory = new RedisTimeSeriesFactory({ port: 6381, db: 15 });\n    const redisTimeSeries = factory.create();\n    const date = new Date(2020, 1, 6, 11).getTime();\n\n    await redisTimeSeries.create(\"range1\");\n    for (let i = 0; i < 10; i++) {\n        await redisTimeSeries.add(new Sample(\"range1\", 20 + i, date + i * 1000));\n    }\n\n    const aggregation = new Aggregation(AggregationType.AVG, 1000);\n    const timestampRange = new TimestampRange(date, date + 10000);\n    const samples = await redisTimeSeries.range(\"range1\", timestampRange, undefined, aggregation);\n\n    for (const sample of samples) {\n        console.log(sample.getKey()); // range1\n        console.log(sample.getValue()); // >=20 and < 30\n        console.log(sample.getTimestamp()); // between 1580983200000 and 1580983209000 timestamp values\n    }\n\n    await redisTimeSeries.delete(\"range1\");\n    await redisTimeSeries.disconnect();\n};\n\nexample();\n```\n\nMore info: [TS.RANGE/TS.REVRANGE](https://oss.redislabs.com/redistimeseries/commands/#tsrangetsrevrange)\n\n### `.multiRange/multiRevRange`\nIt queries a timestamp range across multiple time-series by using filters.\n\n`redisTimeSeries.multiRange(range: TimestampRange, filters: FilterBuilder, count?: number, aggregation?: Aggregation, withLabels?: boolean): Promise<Array<MultiRangeResponse>>`\n\n- `range`: a `TimestampRange` object\n- `filters`: a `FilterBuilder` which will generate an array of filter to be applied across multiple time-series \n- `count`: (optional) maximum number of returned samples per time-series\n- `aggregation`: (optional) aggregation rule\n- `withLabels`: (optional) by default labels will be not included in the response, if true, they will\n\n\n**FilterBuilder**\n\n`FilterBuilder(label: string, value: string | number)`\n\nThe `label` and `value` in the constructor create a first filter where `label=value`. More filters can be created by \ncalling the different methods in `FilterBuilder`:\n- `equal(label: string, value: string | number)`: label=value\n- `notEqual(label: string, value: string | number)`: label!=value\n- `exists(label: string`: label exists in time-series\n- `notExists(label: string`: label doesn't exist in time-series\n- `in(label: string, value: StringNumberArray)`: where value is an array of strings and numbers, it specifies that label is equal to one of the values in the array\n- `notIn(label: string, value: StringNumberArray)`: where value is an array of strings and numbers, it specifies that label is NOT equal to one of the values in the array\n\n**Response**\n\nAn array of `MultiRangeResponse` objects\n\n```\ninterface MultiRangeResponse {\n    key: string;\n    labels: Label[];\n    data: Sample[];\n}\n```\n\nif `withLabels` is true, `labels` in `MultiRangeResponse` will be empty.\n\nIf some of the keys returned by the filter doesn't include any sample because, for instance, the chosen timestamp range \ndoesn't match `MultiRangeResponse.data` will still include one sample in the array with value = 0 and timestamp = first\ntimestamp found in the time-series which will be equel to 0 if the time-series has no data stored. \n\n**Example**\n\n```ts\nimport { \n    Label, \n    Sample, \n    Aggregation, \n    AggregationType, \n    TimestampRange, \n    FilterBuilder, \n    RedisTimeSeriesFactory \n} from \"@emmanuelnk/redis-time-series-ts\";\n\nconst example = async () => {\n    const factory = new RedisTimeSeriesFactory({ port: 6381, db: 15 });\n    const redisTimeSeries = factory.create();\n    const date = new Date(2020, 1, 6, 11).getTime();\n    const label1 = new Label(\"label\", \"1\");\n    const sensor1 = new Label(\"sensor\", \"1\");\n    const sensor2 = new Label(\"sensor\", \"2\");\n\n    await redisTimeSeries.create(\"multirange1\", [label1, sensor1]);\n    await redisTimeSeries.create(\"multirange2\", [label1, sensor2]);\n\n    await redisTimeSeries.create(\"range1\");\n    for (let i = 0; i < 10; i++) {\n        await redisTimeSeries.add(new Sample(\"multirange1\", 20 + i, date + i * 1000));\n        await redisTimeSeries.add(new Sample(\"multirange2\", 30 + i, date + i * 1000));\n    }\n\n    const aggregation = new Aggregation(AggregationType.MAX, 5000);\n    const timestampRange = new TimestampRange(date, date + 10000);\n    const filter = new FilterBuilder(\"label\", 1).equal(\"sensor\", 1);\n    const multiRanges = await redisTimeSeries.multiRange(timestampRange, filter, undefined, aggregation, true);\n    const multiRange = multiRanges.shift();\n    \n    console.log(multiRange.key); //multirange1\n    \n    const labels = multiRange.labels;\n    console.log(labels.shift()); // Label { name: 'label', value: '1' }\n    console.log(labels.shift()); // Label { name: 'sensor', value: '1' }\n\n    \n    const samples = multiRange.data;\n    \n    console.log(samples.shift().getValue()); // 24  \n    console.log(samples.shift().getValue()); // 29;\n    console.log(multiRanges.length); // 0\n\n    await redisTimeSeries.delete(\"range1\");\n    await redisTimeSeries.disconnect();\n};\n\nexample();\n```\n\nMore info: [TS.MRANGE/TS.MREVRANGE](https://oss.redislabs.com/redistimeseries/commands/#tsmrangetsmrevrange)\n\n### `.get`\nGet the last sample from an existing time-series.\n\n`redisTimeSeries.get(key: string): Promise<Sample>`\n\n**Response**\n\nThe last sample in the time-series specified by `key`\n\n**Example**\n\n```ts\nimport { \n    Sample, \n    RedisTimeSeriesFactory \n} from \"@emmanuelnk/redis-time-series-ts\";\n\nconst example = async () => {\n    const factory = new RedisTimeSeriesFactory({ port: 6381, db: 15 });\n    const redisTimeSeries = factory.create();\n    const date = new Date(2020, 1, 6, 11).getTime();\n\n    await redisTimeSeries.add(new Sample(\"get\", 20, date));\n\n    const sample = await redisTimeSeries.get(\"get\");\n\n    console.log(sample.getKey()); // get\n    console.log(sample.getValue()); // 20\n    console.log(sample.getTimestamp()); // 1580983200000;\n\n    await redisTimeSeries.delete(\"get\");\n    await redisTimeSeries.disconnect();\n};\n\nexample();\n```\n\nMore info: [TS.GET](https://oss.redislabs.com/redistimeseries/commands/#tsget)\n\n### `.multiGet`\nGets the last samples matching the specific filter.\n\n`redisTimeSeries.multiGet(filters: FilterBuilder): Promise<Array<MultiGetResponse>>`\n\nThe `filters` param is a `FilterBuilder` which will generate an array of filters to be applied across multiple time-series \n\n**Response**\n\nAn array of `MultiGetResponse` objects\n\n```\ninterface MultiRangeResponse {\n    key: string;\n    labels: Label[];\n    data: Sample;\n}\n```\n\nif `withLabels` is true, `labels` in `MultiRangeResponse` will be empty\n\nIf for a key returned because matches the filter but doesn't contain any data, `MultiGetResponse.data` will contain a \nsample with value = 0 and timestamp = 0;\n\n**Example**\n\n```ts\nimport { \n    FilterBuilder, \n    Sample, \n    Label, \n    RedisTimeSeriesFactory \n} from \"@emmanuelnk/redis-time-series-ts\";\n\nconst example = async () => {\n    const factory = new RedisTimeSeriesFactory({ port: 6381, db: 15 });\n    const redisTimeSeries = factory.create();\n    const date = new Date(2020, 1, 6, 11).getTime();\n    const label1 = new Label(\"label\", \"1\");\n    const sensor1 = new Label(\"sensor\", \"1\");\n    const sensor2 = new Label(\"sensor\", \"2\");\n\n    await redisTimeSeries.create(\"multiget1\", [label1, sensor1]);\n    await redisTimeSeries.create(\"multiget2\", [label1, sensor2]);\n\n    for (let i = 0; i < 10; i++) {\n        await redisTimeSeries.add(new Sample(\"multiget1\", 20 + i, date + i * 1000));\n        await redisTimeSeries.add(new Sample(\"multiget2\", 30 + i, date + i * 1000));\n    }\n\n    const filter = new FilterBuilder(\"label\", 1);\n    const multiGets = await redisTimeSeries.multiGet(filter);\n\n    const multiGet1 = multiGets.shift();\n    console.log(multiGet1.key); // multiget1\n    \n    const labels1 = multiGet1.labels;\n    console.log(labels1.shift()); // Label { name: 'label', value: '1' }\n    console.log(labels1.shift()); // Label { name: 'sensor', value: '1' }\n    \n    const sample1 = multiGet1.data;\n    \n    console.log(sample1.getValue()); // 29\n    console.log(sample1.getTimestamp()); // 1580983209000\n\n    const multiGet2 = multiGets.shift();\n    \n    console.log(multiGet2.key); // multiget2\n    \n    const labels2 = multiGet2.labels;\n    console.log(labels2.shift()); // Label { name: 'label', value: '1' }\n    console.log(labels2.shift()); // Label { name: 'sensor', value: '2' }\n\n    const sample2 = multiGet2.data;\n    \n    console.log(sample2.getValue()); // 39\n    console.log(sample2.getTimestamp()); // 1580983209000\n\n    await redisTimeSeries.delete(\"multiget1\", \"multiget2\");\n    await redisTimeSeries.disconnect();\n};\n\nexample();\n```\n\nMore info: [TS.MULTIGET](https://oss.redislabs.com/redistimeseries/commands/#tsmget)\n\n### `.queryIndex`\nGet all time-series keys matching the filter list.\n\n`redisTimeSeries.mueryIndex(filters: FilterBuilder): Promise<string[]>`\n\nThe `filters` param is a `FilterBuilder` which will generate an array of filter to be applied across multiple time-series \n\n**Response**\n\nAn array of time-series keys\n\n**Example**\n\n```ts\nimport { \n    Label, \n    Sample, \n    FilterBuilder, \n    RedisTimeSeriesFactory \n} from \"@emmanuelnk/redis-time-series-ts\";\n\nconst example = async () => {\n    const factory = new RedisTimeSeriesFactory({ port: 6381, db: 15 });\n    const redisTimeSeries = factory.create();\n    const date = new Date(2020, 1, 6, 11).getTime();\n    const label1 = new Label(\"label\", \"1\");\n    const sensor1 = new Label(\"sensor\", \"1\");\n    const sensor2 = new Label(\"sensor\", \"2\");\n\n    await redisTimeSeries.create(\"query1\", [label1, sensor1]);\n    await redisTimeSeries.create(\"query2\", [label1, sensor2]);\n\n    for (let i = 0; i < 10; i++) {\n        await redisTimeSeries.add(new Sample(\"query1\", 20 + i, date + i * 1000));\n        await redisTimeSeries.add(new Sample(\"query2\", 30 + i, date + i * 1000));\n    }\n\n    const filter = new FilterBuilder(\"label\", 1);\n    const keys = await redisTimeSeries.queryIndex(filter);\n\n    // @ts-ignore\n    console.log(keys.shift()); // query1\n    // @ts-ignore\n    console.log(keys.shift()); // query2\n\n    await redisTimeSeries.delete(\"query1\", \"query2\");\n    await redisTimeSeries.disconnect();\n};\n\nexample();\n```\n\nMore info: [TS.QUERYINDEX](https://oss.redislabs.com/redistimeseries/commands/#tsqueryindex)\n\n### `.info`\nReturns information and statistics a time-series specified by `key`.\n\n`redisTimeSeries.info(key: string): Promise<InfoResponse>`\n\n**Response**\n\nAn `InfoResponse` object\n\n```ts\ninterface InfoResponse {\n    totalSamples: number;\n    memoryUsage: number;\n    firstTimestamp: number;\n    lastTimestamp: number;\n    retentionTime: number;\n    chunkCount: number;\n    chunkSize: number;\n    chunkType: string;\n    labels: Label[];\n    duplicatePolicy: string;\n    sourceKey?: string;\n    rules: AggregationByKey;\n}\n\ninterface AggregationByKey {\n    [key: string]: Aggregation;\n}\n```\n\n**Example**\n\n```ts\nimport { \n    Label, \n    Sample, \n    RedisTimeSeriesFactory \n} from \"@emmanuelnk/redis-time-series-ts\";\n\nconst example = async () => {\n    const factory = new RedisTimeSeriesFactory({ port: 6381, db: 15 });\n    const redisTimeSeries = factory.create();\n    const date = new Date(2020, 1, 6, 11).getTime();\n    const label = new Label(\"label\", \"1\");\n\n    await redisTimeSeries.add(new Sample(\"info\", 20, date), [label], 50000);\n\n    const info = await redisTimeSeries.info(\"info\");\n\n    console.log(info.totalSamples); // 1\n    console.log(info.memoryUsage); // 1\n    console.log(info.firstTimestamp); // 1580983200000\n    console.log(info.lastTimestamp); // 1580983200000\n    console.log(info.retentionTime); // 50000\n    console.log(info.sourceKey); // undefined\n    console.log(info.labels.shift()); // Label { name: 'label', value: '1' }\n    console.log(info.chunkSize); // 256\n    console.log(info.chunkCount); // 1\n    console.log(info.chunkType); // 'uncompressed'\n    console.log(info.duplicatePolicy); // 'LAST'\n    console.log(info.rules); // {}\n\n    await redisTimeSeries.delete(\"info\");\n    await redisTimeSeries.disconnect();\n};\n\nexample();\n```\n\nMore info: [TS.INFO](https://oss.redislabs.com/redistimeseries/commands/#tsinfo)\n\n### `.expire`\nExpires a time-series `key` by using Redis `expire` command.\n\n`redisTimeSeries.expire(key: string, seconds: number): Promise<boolean>`\n- `seconds` must be an integer or an exception will be thrown\n\n### `.delete`\nDeletes a time-series `key` by using Redis `del` command.\n\n`redisTimeSeries.delete(key: string): Promise<boolean>`\n\n**Response**\n\nIt returns `true` if the key was deleted successfully, otherwise `false`.\n\n### `.deleteAll`\nDeletes all keys in the current Redis database by using Redis `flushdb` command.\n\n`redisTimeSeries.deleteAll(): Promise<boolean>`\n\n**Response**\n\nIt returns `true` if all keys were deleted successfully, otherwise `false`.\n\n### `.reset`\nResets a time-series `key` by deleting and then recreating the time-series with the labels and retention specified, if any.\n\n`redisTimeSeries.reset(key: string, labels?: Label[], retention?: number): Promise<boolean>`\n\n**Response**\n\nIt returns `true` if `key` was created successfully, otherwise `false`. If `key` doesn't exist or could not be deleted and \nerror is thrown.\n\n### `.disconnect`\nDisconnects the `RedisTimeSeries` client from Redis server.\n\n`redisTimeSeries.disconnect(): Promise<boolean>`\n\n**Response**\n\nIt returns `true` if the client was disconnected successfully, otherwise `false`.\n\n\n## Testing\nTests can be run locally with docker. `docker.compose.yml` file will build two services:\n- redis-time-series: node container with the source code and all dependent packages installed, where you can run the tests from\n- redislabs-redistimeseries: redis container built from `redislabs/redistimeseries:latest` image\n\nYou can follow these steps to build the Docker services and run the tests:\n- from the command line run: `docker-compose up --build -d` to build the Docker services\n- get access to `redis-times-series` service by running `docker exec -it redis-time-series bash`\n- after getting access to `redis-times-series` service, run `npm run test` from inside to run the tests\n\n\n## License\nRedis-time-series code is distributed under MIT license, see [LICENSE](https://github.com/emmanuelnk/redis-time-series/blob/master/LICENSE) \nfile\n","readmeFilename":"README.md"}