{"id":43989880,"url":"https://github.com/smackem/redis-q","last_synced_at":"2026-02-07T10:33:10.940Z","repository":{"id":37007738,"uuid":"479810432","full_name":"smackem/redis-q","owner":"smackem","description":"A Redis shell (REPL) using a query language similar to C#'s LINQ syntax extension.","archived":false,"fork":false,"pushed_at":"2025-03-18T18:40:20.000Z","size":837,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-18T19:45:07.165Z","etag":null,"topics":["linq","linq-expressions","query","query-language","querydsl","redis","redis-client","repl","sql"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/smackem.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-04-09T18:24:31.000Z","updated_at":"2025-03-18T18:37:31.000Z","dependencies_parsed_at":"2024-04-21T19:17:58.225Z","dependency_job_id":"b867481b-6938-467d-80f3-02c52e1e37d6","html_url":"https://github.com/smackem/redis-q","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/smackem/redis-q","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smackem%2Fredis-q","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smackem%2Fredis-q/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smackem%2Fredis-q/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smackem%2Fredis-q/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/smackem","download_url":"https://codeload.github.com/smackem/redis-q/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smackem%2Fredis-q/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29192682,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-07T07:37:03.739Z","status":"ssl_error","status_checked_at":"2026-02-07T07:37:03.029Z","response_time":63,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["linq","linq-expressions","query","query-language","querydsl","redis","redis-client","repl","sql"],"created_at":"2026-02-07T10:33:10.396Z","updated_at":"2026-02-07T10:33:10.934Z","avatar_url":"https://github.com/smackem.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# redis-q\n\n![build](https://github.com/smackem/redis-q/actions/workflows/dotnet.yml/badge.svg)\n\nA REPL to run queries against a [Redis](https://www.redis.io) database using a language similar to C#'s `from` clause.\n\n![image](doc/screenshot-intro-3.png)\n\n## Features\n\nRedis-Q\n- works with [Redis](https://www.redis.io) 5 or newer\n- supports the basic Redis data types: string, list, hash, set and sorted set\n- allows you to write queries in a relational manner to examine the data stored in your Redis instance\n- supports well known operations like cross join and sub-queries as well as aggregations like sum, avg, distinct, count, min and max\n- is able to extract JSON values using JSON-Path\n- works on any desktop platform\n- only supports query (read) commands - use `redis-cli` for writing to the database\n\n## Installation\n\n* Download and extract the [release zip file](https://github.com/smackem/redis-q/releases) fitting your platform to any directory\n* From this directory, run `redis-q` to connect to redis at localhost:6379\n* To connect to a different host or port, enter `redis-q \u003chostname\u003e:\u003cport\u003e`\n* `redis-q --help` shows all command-line options\n\n## Samples\n\nAssume you create a sample data set in your redis instance (using `redis-cli`) consisting of users and sessions, where one user is associated to n sessions:\n```redis-cli\nSET user-1 '{ \"name\":\"bob\" }'\nSET user-2 '{ \"name\":\"alice\" }'\nHSET session-1 user-key user-1 status open startTime \"2022-04-01 22:03:54\"\nHSET session-2 user-key user-1 status closed startTime \"2022-03-29 20:14:02\"\nHSET session-3 user-key user-1 status closed startTime \"2022-03-30 21:03:51\"\nHSET session-4 user-key user-2 status closed startTime \"2022-03-30 19:22:51\"\nHSET session-5 user-key user-2 status open startTime \"2022-04-01 19:22:30\"\n```\nNow start redis-q and enter the following query to join users and sessions:\n```csharp\nfrom userKey in SCAN(\"user-*\")\nfrom sessionKey in SCAN(\"session-*\") \nwhere HGET(sessionKey, \"user-key\") == userKey \n   \u0026\u0026 HGET(sessionKey, \"status\") == \"open\"\nlet sessionStart = HGET(sessionKey, \"startTime\")\nselect (user: userKey, loggedInSince: sessionStart);\n```\n\n```\nuser    loggedInSince      \n---------------------------\nuser-2  2022-04-01 19:22:30\nuser-1  2022-04-01 22:03:54\n```\nThe following query will display id ('key') and name of users that are currently logged in: \n```csharp\nfrom userKey in SCAN(\"user-*\")\nlet openSessionCount = \n    from sessionKey in SCAN(\"session-*\") \n    where HGET(sessionKey, \"user-key\") == userKey \n    where HGET(sessionKey, \"status\") == \"open\" \n    select sessionKey \n    |\u003e count()\nwhere openSessionCount \u003e 0\nlet userJson = GET(userKey) \nselect (key: userKey, name: userJson[\".name\"]);\n```\n\n```\nkey     name \n-------------\nuser-2  alice\nuser-1  bob  \n```\n\n## Syntax\nredis-q (or more precisly RedisQL, the query language employed by redis-q) uses a slightly extended subset of C#'s LINQ syntax extension:\n\nhttps://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/from-clause\n\nRedisQL adds the following language features not supported by C#:\n| Feature | Example |\n| --- | ---|\n| F#-like argument pipelining | `[1,2,3] \\|\u003e join(',')` |\n| Ranges | `collect(0..100)` |\n| Single-quoted or double-quoted string literals | `'hello' + \", world\"` |\n| List expressions | `[1, true, 'string']` |\n| Regex operator | `\"abc\" =~ \"\\w{3}\" // true` |\n| Top-level `let` statements | `let x = 1` |\n| The `limit` clause | `from ... limit 10 offset 1 ...` |\n| Case-insensitive function names | `SCAN('*')` is the same as `scan('*')` |\n\n### Basics and operators\nRedisQL supports the following operators, basically a subset of the common operators found in C, C# or Java:\n| Operator | Description |\n| --- | --- |\n| `condition ? a : b` | a if condition is true, otherwise b |\n| `a == b` | Test for equality |\n| `a != b` | Test for inequality |\n| `a \u003c b` | Less than |\n| `a \u003c= b` | Less than or equal |\n| `a \u003e b` | Greater than |\n| `a \u003e= b` | Greater than or equal |\n| `a =~ b` | String-like value a matches the regex pattern b |\n| `a !~ b` | String-like value a does not match the regex pattern b |\n| `a + b` | Add numbers a and b or concatenate strings, if a or b is a string |\n| `a - b` | Subtract number b from number a |\n| `a * b` | Multiply numbers a and b |\n| `a / b` | Divide number a by number b |\n| `a % b` | Modulo of numbers a and b |\n| `a ?? b` | a if not null, otherwise b |\n\nAutomatic type conversion: integer is automatically converted to real in expressions like `1 + 2.5`.\nWhen operators require a string-like type, RedisQL converts operands implicitly to string.\n\n### The `from` expression\nLike C#'s `from` expression, RedisQL's `from` is a lazy iteration construct that enumerates all values in the source collection and binds each value to the iterator identifier.\n\nSimple example: `from x in 1..3 select x` selects the identity of the source range `1..3`, the numbers 1, 2 and 3.\nIn this case, the range `1..3` is the source collection and `x` is the iterator identifier.\n\nThe source collection may be any enumerable value: ranges, lists and enumerables produced by functions or other `from` expressions.\n\nThe selection may be any expression using any bindings declared by the `from` expression, e.g.\n`from x in 1..3 select x + 1`, which selects 2,3 and 4.\n\nNested bindings allow storing of intermediate results withing the `from` expression:\n```csharp\nfrom x in [1,2,3]\nlet s = x * x\nselect (base: x, squared: s);\n```\n```\nbase  squared\n-------------\n1     1      \n2     4      \n3     9      \n```\n\nCarthesian products (\"cross joins\" in SQL) can be produced by chaining `from` clauses:\n```csharp\nfrom x in [1,2,3]\nfrom y in [10,11]\nselect (x: x, y: y, product: x * y)\n```\n```\nx  y   product\n--------------\n1  10  10     \n1  11  11     \n2  10  20     \n2  11  22     \n3  10  30     \n3  11  33     \n```\nFiltering of enumerables can be achieved using the `where` clause:\n```csharp\nfrom x in [0,1,2,3,4]\nwhere x % 2 == 0\nselect x\n```\n```\n  0\n  2\n  4\n```\n\nOrdering of items can be achieved with the `orderby` clause:\n```csharp\nfrom x in [15, 4, -10, 30, -22]\nlet squared = x * x\norderby x\nselect (x: x, squared: squared)\n```\n```\nx    squared\n------------\n-22  484    \n-10  100    \n4    16     \n15   225    \n30   900    \n```\nTo reverse the sort order, use the `descending` keyword:\n`from x in 1..10 orderby x descending select x` basically is the same as `1..10 |\u003e reverse()`.\n\nLimiting the result set can be achieved with the `limit` clause, which is familiar from SQL:\n```csharp\nfrom x in [1,2,3,4,5,6,8,9,10] \nwhere x % 2 == 0 \nlimit 3 offset 1 \nselect x;\n```\n```\n  4\n  6\n  8\n```\n\nNote that the `offset` clause is optional and the default offset is 0.\n\nWhen working with large data sets, including a `limit` clause in all queries against keyspace-scans (like `keys()` or `zscan()`) is good practice.\n\nAs in C#, you can use the `group by` clause to group results based on common criteria:\n```csharp\nfrom x in [1,2,3,4,5,6,7,8,9,10]\ngroup x by x % 2 into g\nselect g;\n```\n```\nkey  values          \n---------------------\n1    [1, 3, 5, 7, 9] \n0    [2, 4, 6, 8, 10]\n\n2 element(s)\n```\n\nThe target identifier (in this example `g`) is assigned a tuple with fields `(key, values)`.\nOne of the first samples in this documents - collecting open sessions per user - can be rewritten like this, using the `group by` clause:\n\n```csharp\nfrom userKey in SCAN(\"user-*\") \nfrom sessionKey in SCAN(\"session-*\") \nwhere HGET(sessionKey, \"user-key\") == userKey \nwhere HGET(sessionKey, \"status\") == \"open\"\ngroup sessionKey by userKey into g \nlet userJson = GET(userKey) \nselect (key: g.key, name: userJson[\".name\"], openSessions: count(g.values));\n```\n```\nkey     name   openSessions\n---------------------------\nuser-2  alice  1           \nuser-1  bob    1           \n\n2 element(s)\n```\n\n### Functions and Pipelining\nredis-q features a collection of built-in functions, which can be invoked as usual in languages like C or Java:\n```csharp\ncount([1,2,3]);\n```\n```\n3\n```\nAll Redis-specific functionality in redis-q is built using functions. A full list of supported functions can be found below.\n\nOne feature taken from F# comes in handy for a REPL: the possibility to pipe arguments to a function call using the `|\u003e` operator. The above sample can also be written like this:\n```csharp\n[1,2,3] |\u003e count()\n```\nThe operand preceding the `|\u003e` operator is passed as the _last_ argument to the function on the right.\nThis enables fluent typing of expressions like\n```csharp\nfrom x in [1,2,3,2,1]\nselect x\n|\u003e distinct();\n```\n```\n1\n2\n3\n```\nor the following:\n```csharp\nfrom x in [15, 4, -10, 30, -22]\nlet squared = x * x\norderby x\nselect squared\n|\u003e join(\"+\");\n```\n```\n484+100+16+225+900\n```\n\nSince v0.3.0, redis-q also supports defining user functions. See 'Bindings' below for more info.\n\n## Data Types\nRedisQL is a dynamically-typed language supporting scalar values like integers or strings as well as composite values like lists, enumerables and tuples.\n\n### Scalar types\nRedisQL supports the following scalar data types:\n| Name | Description | Literal |\n| --- | --- | --- |\n| int | 64 bit signed integer | `100` or `1_000_000` |\n| real | 64 bit floating point | `12.5` or `1_125.000_001` |\n| string | unicode string of arbitrary length | `\"hello\"` or `'world'` |\n| bool | boolean value | `true` or `false` |\n| timestamp | date and time | see below |\n| duration | a time span | see below |\n\nRedis values are implicitly converted to the type required by the operation.\nRedis keys are implictly convertible to string.\n\n### Conversion to Boolean\nAll RedisQL values except tuples and lazy enumerables can be converted to boolean:\n| Type | `false` if |\n| --- | ---|\n| list | empty |\n| string | empty |\n| integer | 0 |\n| real | 0.0 |\n| bool | false |\n| any | null |\n| duration | zero |\n\n### Enumerables, List and Ranges\nEnumerables in RedisQL are lazily evaluated, whereas lists are discrete collections (as in dotnet `IEnumerable` vs. `IList` or in `Stream` vs. `Collection` in Java).\nEnumerables and lists are displayed differently:\n`1..3` evaluates to\n```\n  1\n  2\n  3\nEnumerated 3 element(s)\n```\nwhile `[1,2,3];` evaluates to\n```\n[1, 2, 3]\n```\nThe expression `1..3` denotes a Range, which is a simple enumerable over an *inclusive* range of integers.\n\nThe `from` expression usually produces an Enumerable, except when it is nested in another `from` expression. In the latter case, it always evaluated eagerly and produces a List:\n\n```csharp\nfrom x in [1, 2, 3]\nfrom y in [10, 100, 1000] \nselect x * y;\n```\n```\n  10\n  100\n  1000\n  20\n  200\n  2000\n  30\n  300\n  3000\n```\nWhereas:\n```csharp\nfrom x in [1, 2, 3]\nlet m =\n    from y in [10, 100, 1000]\n    select x * y\nselect m;\n```\n```\n  [10, 100, 1000]\n  [20, 200, 2000]\n  [30, 300, 3000]\n```\n\nLists, opposed to Enumerables, can be indexed using the subscript operator:\n```\nlet l = [100, 200, 300];\nl[0]\n```\n```\n100\n```\n\nThe index can either be an integer or a range to extract a sub-list (slice) from the list:\n```\nl[0..1]\n```\n```\n[100, 200]\n```\n\n### Tuples\nTuples are composite values consisting of at least two elements like `(1, \"abc\")`.\nIn contrast to lists, tuple elements are called fields and can be named:\n```csharp\nlet user = (name: \"bob\", role: \"admin\");\n```\nredis-q displays collections of uniform tuples in tables:\n```csharp\n\u003e let users = [(name: \"bob\", role: \"admin\"), (name: \"alice\", role: \"guest\")];\n\nname   role \n------------\nbob    admin\nalice  guest\n```\n\nTuple fields can be accessed either by index or by name (if the tuple has named fields):\n```csharp\nlet user = (name: \"bob\", role: \"admin\");\nlet userName = user.name;\nlet userRole = user.role;\n```\nor\n```csharp\nlet user = (name: \"bob\", role: \"admin\");\nlet userName = user[0];\nlet userRole = user[1];\n```\n\n### The `null` value\nThe `null` literal signals the absence of a value.\n\n```csharp\nlet george =\n    from k in KEYS('user-*')\n    where GET(k)[\".name\"] == \"george\"\n    select k\n    |\u003e first();\n```\n```csharp\n// user george does not exist, so first() returns null\nnull\n```\n\nArithmetic operators applied to at least one `null` operand yield `null` as result:\n```csharp\n1 + null == null;\n```\n```\nTrue\n```\n\nIn string concatenation, `null` is equivalent to the empty string `\"\"`:\n```csharp\n\"abc\" + null == \"abc\";\n```\n```\nTrue\n```\n\nAggregation function like `sum` or `avg` ignore `null` values in enumerables.\n\n`null` converted to bool is `false`.\n\n### Timestamp and duration values (since v0.2.0)\n\nThe function `timestamp(\"2022-05-01 12:04:55.123\", \"yyyy-MM-dd HH:mm:ss.fff\")` creates a value of type `timestamp`.\n`deconstruct(ts)` returns a tuple that allows access to year, month, day etc:\n```\n\u003e timestamp(\"2022-05-01 12:04:55.123\", \"yyyy-MM-dd HH:mm:ss.fff\");\n2022-05-01 12:04:55 +02\n\u003e deconstruct(it);\n(year: 2022, month: 5, day: 1, hour: 12, minute: 4, second: 55, millisecond: 123)\n```\n\nThe function `duration(1, 's')` can be used to create duration values:\n```\n\u003e duration(1, 's');\n0:00:01\n\u003e duration(10, 'ms');\n0:00:00.01\n```\n\nUse `convert(unit, value)` to convert durations into total hours, seconds or milliseconds:\n```\n\u003e duration(10, \"ms\");                                             \n0:00:00.01\n\u003e convert(\"ms\", it);\n10\n```\n\nAdditive operations work on timestamp and duration values: You can add durations to timestamps and to other durations.\n\nThe function `now()` returns the current timestamp.\n```\n\u003e now();\n2022-05-15 19:05:22 +02\n```\n\n## JSON Support\nredis-q supports querying JSON objects using JSONPath (see https://github.com/json-path/JsonPath) and the subscript syntax for strings:\n\n```csharp\nlet json = \"{ foo: 'bar', answer: 42 }\";\n\njson[\"$.answer\"];\n```\n```\n42\n```\n\nValues extracted from JSON are translated to their corresponding RedisQL types, so a JSON integer values becomes a RedisQL integer, a JSON array becomes a RedisQL list etc.\n\n## Bindings\nBind values anytime in the REPL's top most scope using the `let` statement:\n```csharp\n\u003e let multiplier = 100;\n100\n\u003e let numbers = [1, 2, 3];\n[1, 2, 3]\n\u003e let products = from n in numbers select n * multiplier |\u003e collect();\n[100, 200, 300]\n\u003e let userNames = from k in SCAN(\"user-*\") select GET(k)[\".name\"] |\u003e collect();    \n[alice, bob]\n```\nThe last evaluation's result can be recalled using the identifier `it`:\n```csharp\n\u003e 1 + 1;\n2\n\u003e it;\n2\n\u003e it + 1;\n3\n```\n\nIt's best to bind top-level values to discrete lists instead of enumerations so the value can be iterated multiple times using the `it` identifier. This is why the `collect()` function is used in the preceding samples.\n\nSince v0.3.0, redis-q supports function expressions:\n\n```\n\u003e let carthesian(itemsA, itemsB) =\n    from a in itemsA\n    from b in itemsB\n    select (a: a, b: b);\ncarthesian(a, b)\n\u003e carthesian(0..1, 0..1);\na  b\n----\n0  0\n0  1\n1  0\n1  1\n```\n\nThe body of a function consists of a single expression. To enable top-level `let` bindings in functions, redis-q 0.3.0 supports the F#-like `let .. in ..` expression:\n```fsharp\n\u003e let a = 100 in\n  let b = 200 in\n  a + b;\n```\n```\n300\n```\n\nThis is a single expression which defines two bindings: the value 100 is bound to identifier `a` and the value 200 is bound to identifier `b`.\n\nTo define a function that stores intermediate results in bindings, you can write\n\n```fsharp\nlet randomRange(maxLength) =\n    let lower = random(0, 1000) in\n    let upper = lower + random(0, maxLength) in\n    lower .. upper;\n```\n\n## REPL shell commands (since v0.2.0)\n\n| Command | Description |\n| --- | --- |\n| `#q;` | Quits the REPL |\n| `#h;` | Displays all available functions |\n| `#pwd;` | Displays the current directory |\n| `#cd \u003cDIR\u003e;` | Changes to the directory `\u003cDIR\u003e` |\n| `#ls;` | Lists all file system entries in the current directory |\n| `#dump;` | Prints all top-level bindings |\n\n## REPL shell commands (since v0.3.0)\n\n| Command | Description |\n| --- | --- |\n| `#load \u003cFILE\u003e;` | Loads and interprets RedisQL source from `\u003cFILE\u003e` |\n\n## Built-in functions\n\nNote that from v0.2.0 on, function names are case-insensitive. Redis functions are defined in upper-case and common functions in lower case. Case sensitivity can be enforced with a new command line parameter `-c`.\n\n### Common functions\n| Signature | Description |\n| --- | --- |\n| `size(list\\|string) -\u003e int`| Returns the number of elements in the list or string |\n| `count(enumerable) -\u003e int`| Returns the number of elements produced by the enumerable |\n| `int(any) -\u003e int`| Converts any value to int or returns `null` |\n| `real(any) -\u003e real`| Converts any value to real or returns `null` |\n| `bool(any) -\u003e bool`| Converts any value to bool or returns `null` |\n| `string(any) -\u003e string`| Converts any value to string |\n| `lower(string) -\u003e string`| Converts a string to lower case |\n| `upper(string) -\u003e string`| Converts a string to upper case |\n| `match(input: string, pattern: string) -\u003e list`| Returns a list of all groups matched in input by the regex pattern |\n| `collect(enumerable) -\u003e list`| Enumerates all values in an enumerable and collects them in a list |\n| `join(separator: string, coll: enumerable) -\u003e string`| Enumerates all values in an enumerable and aggregates them in a string, separated by the first argument |\n| `distinct(enumerable) -\u003e enumerable`| Yields all distinct values in an enumerable, removing duplicates |\n| `sum(enumerable) -\u003e value`| Returns the sum of all values in the enumerable |\n| `avg(enumerable) -\u003e number`| Returns the average of all values in the enumerable, which must only contain numbers or `null` values |\n| `min(enumerable)` -\u003e value| Returns the minimum of all values in the enumerable, which must only contain numbers or `null` values |\n| `max(enumerable) -\u003e value`| Returns the maximum of all values in the enumerable, which must only contain numbers or `null` values |\n| `first(enumerable) -\u003e value`| Returns the first non-null value in enumerable or `null` if none found |\n| `any(enumerable) -\u003e bool`| Returns `true` if there is at least one non-null value in enumerable, otherwise `false` |\n| `reverse(enumerable) -\u003e enumerable`| Yields all values in the enumerable in reverse order |\n| `sort(enumerable) -\u003e enumerable`| Yields all values in the enumerable sorted, with strings \u003e numbers |\n\nv0.2.0 adds a lot of functions, see the inline help by entering `#h;` in the REPL for more.\nHighlights include functions to create and convert `timestamp` and `duration` values, standard math functions and `clip` (copy to clipboard) as well as `save` (save value to file).\n\n### Redis functions\n\n| Redis Command, see https://redis.io/commands/ | Signature |\n| --- | --- |\n| EXISTS        | (key) -\u003e bool                                          |\n| GET           | (key) -\u003e value                                         |\n| GETRANGE      | (key, start: int, end: int) -\u003e value                   |\n| HEXISTS       | (key, field: value) -\u003e bool                            |\n| HGET          | (key, field: value) -\u003e value                           |\n| HGETALL       | (key) -\u003e list of tuple(name: string, value: value)     |\n| HKEYS         | (key) -\u003e list of keys                                  |\n| HLEN          | (key) -\u003e int                                           |\n| HMGET         | (key, list of field: value) -\u003e list of value           |\n| HSCAN         | (key, pattern: value) -\u003e enumerable                    |\n| HSTRLEN       | (key, field: value) -\u003e int                             |\n| HVALS         | (key) -\u003e list of value                                 |\n| KEYS          | (pattern) -\u003e enumerable                                |\n| LINDEX        | (key, index: int) -\u003e value                             |\n| LLEN          | (key) -\u003e int                                           |\n| LRANGE        | (key, start: int, end: int) -\u003e list                    |\n| MGET          | (list of keys) -\u003e list of values                       |\n| RANDOMKEY     | () -\u003e key                                              |\n| SCAN          | (pattern) -\u003e enumerable                                |\n| SCARD         | (key) -\u003e int                                           |\n| SDIFF         | (key, key) -\u003e list of value                            |\n| SINTER        | (key, key) -\u003e list of value                            |\n| SISMEMBER     | (key, value) -\u003e bool                                   |\n| SMEMBERS      | (key) -\u003e list of value                                 |\n| SRANDOMMEMBER | (key) -\u003e value                                         |\n| SSCAN         | (key, pattern: value) -\u003e enumerable                    |\n| STRLEN        | (key) -\u003e int                                           |\n| SUNION        | (key, key) -\u003e list of value                            |\n| TYPE          | (key) -\u003e string                                        |\n| ZCARD         | (key) -\u003e int                                           |\n| ZCOUNT        | (key, minScore: real, maxScore: real) -\u003e int           |\n| ZRANGE        | (key, start: int, end: int) -\u003e list of value           |\n| ZRANGEBYSCORE | (key, minScore: real, maxScore: real) -\u003e list of value |\n| ZRANK         | (key, value) -\u003e int                                    |\n| ZSCAN         | (key, pattern: value) -\u003e enumerable                    |\n| ZSCORE        | (key, value) -\u003e real                                   |\n\n## More language features\n\n### `throw` Expressions\n\nJust like C#, RedisQL supports the `throw` expression:\n\n```csharp\n(keys(\"sysinfo-*\") |\u003e any()) || throw \"no sysinfo found!\"\n```\nAny value can be thrown, though it is best practice to throw strings, since the thrown value\nwill be presented to the user.\n\nIn contrast to c#, throw expressions may appear anywhere, not just in ternary expressions or on the right side of the null-coalescing operator.\n\nSo this is possible, though it does not make too much sense:\n\n`1 + throw \"why not?\"`\n\n## Build and Run\n\n- Install .net SDK 6.0 or higher\n- Clone the repository\n- From the repo source directory, run  \n  `dotnet run --project src/RedisQ.Cli`\n- Per default, redis-q connects to Redis at localhost:6379, but you can pass a different connection string when executing redis-q. Run  \n  `dotnet run --project src/RedisQ.Cli --help`  \n  to see all command-line options.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsmackem%2Fredis-q","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsmackem%2Fredis-q","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsmackem%2Fredis-q/lists"}