diff --git a/build/components/component.py b/build/components/component.py index 2ab2077863..9987b20b38 100644 --- a/build/components/component.py +++ b/build/components/component.py @@ -249,7 +249,45 @@ def _copy_examples(self): logging.info(f'Copying {self._id} examples to {dst}') + content_filter = ex.get('content_filter') + for f in glob.glob(os.path.join(src, ex.get('pattern')), recursive=True): + # Apply content filter if specified + if content_filter: + with open(f, 'r', encoding='utf-8', errors='ignore') as cf: + file_lines = cf.readlines() + contains = content_filter.get('contains') + not_contains = content_filter.get('not_contains') + exclude_line = content_filter.get('exclude_line_contains') + + if contains: + # At least one line must contain `contains`, ignoring + # any lines that also contain `exclude_line` (if set). + matched = any( + contains in line and + (exclude_line is None or exclude_line not in line) + for line in file_lines + ) + if not matched: + logging.debug( + f'Skipping {f}: no qualifying line contains "{contains}"' + ) + continue + + if not_contains: + # No line may contain `not_contains`, ignoring any + # lines that also contain `exclude_line` (if set). + has_disqualifying = any( + not_contains in line and + (exclude_line is None or exclude_line not in line) + for line in file_lines + ) + if has_disqualifying: + logging.debug( + f'Skipping {f}: found disqualifying line with "{not_contains}"' + ) + continue + example_id = self._get_example_id_from_file(f) if not example_id: diff --git a/build/local_examples.py b/build/local_examples.py index 2475959d29..d8503fb4d7 100644 --- a/build/local_examples.py +++ b/build/local_examples.py @@ -40,7 +40,7 @@ 'node.js': 'Node.js', 'go': 'Go', 'c': 'C', - 'c#': 'C#-Sync', + 'c#': 'C#-Sync (NRedisStack)', # Default; overridden by content check in get_client_name_from_language_and_path 'java': 'Java-Sync', # Default to sync, could be overridden 'php': 'PHP', 'ruby': 'Ruby', @@ -48,6 +48,26 @@ 'rust': 'Rust-Sync' } +# Marker used to identify NRedisStack examples (matches any NRedisStack namespace import) +NREDISSTACK_IMPORT_MARKER = 'using NRedisStack' +# Test-infrastructure import that appears in every C# file regardless of client +NREDISSTACK_TEST_IMPORT = 'using NRedisStack.Tests' + + +def is_nredisstack_example(content: str) -> bool: + """Return True if the file genuinely uses NRedisStack. + + Checks line by line for NREDISSTACK_IMPORT_MARKER ('using NRedisStack'), + but ignores lines that contain NREDISSTACK_TEST_IMPORT ('using NRedisStack.Tests') + because that import appears in every C# test file as test-infrastructure + boilerplate, regardless of whether the example uses NRedisStack or plain + StackExchange.Redis. + """ + return any( + NREDISSTACK_IMPORT_MARKER in line and NREDISSTACK_TEST_IMPORT not in line + for line in content.splitlines() + ) + def get_language_from_extension(filename: str) -> str: """Get language from file extension.""" @@ -60,8 +80,9 @@ def get_client_name_from_language(language: str) -> str: return LANGUAGE_TO_CLIENT.get(language, language.title()) -def get_client_name_from_language_and_path(language: str, path: str) -> str: - """Get client name from language with path-based overrides. +def get_client_name_from_language_and_path(language: str, path: str, + content: str = '') -> str: + """Get client name from language with path-based and content-based overrides. For JavaScript (.js) files, override based on path substrings: - If 'ioredis' in path -> ioredis @@ -72,6 +93,12 @@ def get_client_name_from_language_and_path(language: str, path: str) -> str: - If 'lettuce-async' in path -> Java-Async - If 'lettuce-reactive' in path -> Java-Reactive + For C# (.cs) files, override based on path substrings and file content: + - Sync vs Async determined by 'async' appearing in the path + - NRedisStack vs SE.Redis determined by the presence of NREDISSTACK_IMPORT_MARKER + ('using NRedisStack') anywhere in the file content, which matches both the root + namespace import and any subnamespace imports (e.g. 'using NRedisStack.Search;'). + Substring checks are case-sensitive and can appear anywhere in the path. """ if language == 'node.js': @@ -90,10 +117,9 @@ def get_client_name_from_language_and_path(language: str, path: str) -> str: if 'rust-sync' in path: return 'Rust-Sync' if language == 'c#': - if 'async' in path: - return 'C#-Async' - if 'sync' in path: - return 'C#-Sync' + variant = 'Async' if 'async' in path else 'Sync' + client = 'NRedisStack' if is_nredisstack_example(content) else 'SE.Redis' + return f'C#-{variant} ({client})' # Default behavior for all languages (and Java fallback) return get_client_name_from_language(language) @@ -180,11 +206,17 @@ def process_local_examples(local_examples_dir: str = 'local_examples', target_file = os.path.join(target_dir, target_filename) shutil.copy2(source_file, target_file) + # Read source file content for content-based client detection + # (must be done before Example processes the copy, which strips markers) + with open(source_file, 'r', encoding='utf-8', errors='ignore') as sf: + source_content = sf.read() + # Process with Example class example = Example(language, target_file) - # Get client name (with Java path-based overrides) - client_name = get_client_name_from_language_and_path(language, source_file) + # Get client name (with path-based and content-based overrides) + client_name = get_client_name_from_language_and_path( + language, source_file, source_content) # Create metadata example_metadata = { diff --git a/config.toml b/config.toml index 872a3a0eaf..9af405b67c 100644 --- a/config.toml +++ b/config.toml @@ -46,7 +46,7 @@ tagManagerId = "GTM-TKZ6J9R" gitHubRepo = "https://github.com/redis/docs" # Display and sort order for client examples -clientsExamples = ["Python", "Node.js", "ioredis", "Java-Sync", "Lettuce-Sync", "Java-Async", "Java-Reactive", "Go", "C", "C#-Sync", "C#-Async", "RedisVL", "PHP", "Ruby", "Rust-Sync", "Rust-Async"] +clientsExamples = ["Python", "Node.js", "ioredis", "Java-Sync", "Lettuce-Sync", "Java-Async", "Java-Reactive", "Go", "C", "C#-Sync (NRedisStack)", "C#-Async (NRedisStack)", "C#-Sync (SE.Redis)", "C#-Async (SE.Redis)", "RedisVL", "PHP", "Ruby", "Rust-Sync", "Rust-Async"] searchService = "/convai/api/search-service" ratingsService = "/docusight/api/rate/docs" @@ -70,8 +70,10 @@ rdi_current_version = "1.16.2" "Java-Reactive"={quickstartSlug="lettuce", langId="java", clientId="lettuce", clientName="Lettuce", mappingClientId="lettuce_reactive"} "Go"={quickstartSlug="go", langId="go", clientId="go-redis", clientName="go-redis", mappingClientId="go-redis"} "C"={quickstartSlug="hiredis", langId="c", clientId="hiredis", clientName="hiredis", mappingClientId=""} -"C#-Sync"={quickstartSlug="dotnet", langId="csharp", clientId="stackexchange-redis", clientName="StackExchange.Redis", mappingClientId="nredisstack_sync"} -"C#-Async"={quickstartSlug="dotnet", langId="csharp", clientId="stackexchange-redis", clientName="StackExchange.Redis", mappingClientId="nredisstack_async"} +"C#-Sync (NRedisStack)"={quickstartSlug="dotnet", langId="csharp", clientId="nredisstack", clientName="NRedisStack", mappingClientId="nredisstack_sync"} +"C#-Async (NRedisStack)"={quickstartSlug="dotnet", langId="csharp", clientId="nredisstack", clientName="NRedisStack", mappingClientId="nredisstack_async"} +"C#-Sync (SE.Redis)"={quickstartSlug="dotnet", langId="csharp", clientId="stackexchange-redis", clientName="StackExchange.Redis", mappingClientId="nredisstack_sync"} +"C#-Async (SE.Redis)"={quickstartSlug="dotnet", langId="csharp", clientId="stackexchange-redis", clientName="StackExchange.Redis", mappingClientId="nredisstack_async"} "RedisVL"={quickstartSlug="redis-vl", langId="python", clientId="redis-vl", clientName="RedisVL", mappingClientId="redis_vl"} "PHP"={quickstartSlug="php", langId="php", clientId="predis", clientName="Predis", mappingClientId="php"} "Ruby"={quickstartSlug="redis-rb", langId="ruby", clientId="redis-rb", clientName="redis-rb", mappingClientId="redis_rb"} diff --git a/content/develop/_index.md b/content/develop/_index.md index 3fcb776f8e..1fc69d05b2 100644 --- a/content/develop/_index.md +++ b/content/develop/_index.md @@ -18,7 +18,7 @@ or analyze and manage your database with our | | Get started | Document search | Vector search | |:----- | :-----: | :-----: | :-----:| | [Python]({{< relref "/develop/clients/redis-py" >}}) | [See Python examples]({{< relref "/develop/clients/redis-py/connect" >}}) | [See Python examples]({{< relref "/develop/clients/redis-py/queryjson" >}}) | [See Python examples]({{< relref "/develop/clients/redis-py/vecsearch" >}}) | -| [C#/.NET]({{< relref "/develop/clients/dotnet" >}}) | [See C# examples]({{< relref "/develop/clients/dotnet/connect" >}}) | [See C# examples]({{< relref "/develop/clients/dotnet/queryjson" >}}) | [See C# examples]({{< relref "/develop/clients/dotnet/vecsearch" >}}) | +| [C#/.NET]({{< relref "/develop/clients/dotnet" >}}) | [See C# examples]({{< relref "/develop/clients/dotnet/connect" >}}) | [See C# examples]({{< relref "/develop/clients/dotnet/nredisstack/queryjson" >}}) | [See C# examples]({{< relref "/develop/clients/dotnet/nredisstack/vecsearch" >}}) | | [Node.js]({{< relref "/develop/clients/nodejs" >}}) | [See JS examples]({{< relref "/develop/clients/nodejs/connect" >}}) | [See JS examples]({{< relref "/develop/clients/nodejs/queryjson" >}}) | [See JS examples]({{< relref "/develop/clients/nodejs/vecsearch" >}}) | | [Java (Jedis)]({{< relref "/develop/clients/jedis" >}}) | [See Java examples]({{< relref "/develop/clients/jedis/connect" >}}) | [See Java examples]({{< relref "/develop/clients/jedis/queryjson" >}}) | [See Java examples]({{< relref "/develop/clients/jedis/vecsearch" >}}) | | [Java (Lettuce)]({{< relref "/develop/clients/lettuce" >}}) | [See Java examples]({{< relref "/develop/clients/lettuce/connect" >}}) | [See Java examples]({{< relref "/develop/clients/lettuce/queryjson" >}}) | [See Java examples]({{< relref "/develop/clients/lettuce/vecsearch" >}}) | diff --git a/content/develop/ai/_index.md b/content/develop/ai/_index.md index 5acffe0dad..3c39050d5c 100644 --- a/content/develop/ai/_index.md +++ b/content/develop/ai/_index.md @@ -44,7 +44,7 @@ This page is organized into a few sections depending on what you're trying to do #### Learn how to index and query vector embeddings * [redis-py (Python)]({{< relref "/develop/clients/redis-py/vecsearch" >}}) -* [NRedisStack (C#/.NET)]({{< relref "/develop/clients/dotnet/vecsearch" >}}) +* [NRedisStack (C#/.NET)]({{< relref "/develop/clients/dotnet/nredisstack/vecsearch" >}}) * [node-redis (JavaScript)]({{< relref "/develop/clients/nodejs/vecsearch" >}}) * [Jedis (Java)]({{< relref "/develop/clients/jedis/vecsearch" >}}) * [go-redis (Go)]({{< relref "/develop/clients/go/vecsearch" >}}) diff --git a/content/develop/clients/_index.md b/content/develop/clients/_index.md index 3f9fafded6..d4919f474c 100644 --- a/content/develop/clients/_index.md +++ b/content/develop/clients/_index.md @@ -29,7 +29,8 @@ for nine main languages: | :-- | :-- | :-- | :-- | | [Python](https://www.python.org/) | [`redis-py`](https://github.com/redis/redis-py) |[`redis-py` guide]({{< relref "/develop/clients/redis-py" >}}) | Yes | | [Python](https://www.python.org/) | [`RedisVL`](https://github.com/redis/redis-vl-python) |[RedisVL guide]({{< relref "/develop/ai/redisvl" >}}) | Yes -| [C#/.NET](https://learn.microsoft.com/en-us/dotnet/csharp/) | [`NRedisStack`](https://github.com/redis/NRedisStack) |[`NRedisStack` guide]({{< relref "/develop/clients/dotnet" >}}) | Yes | +| [C#/.NET](https://learn.microsoft.com/en-us/dotnet/csharp/) | [`StackExchange.Redis`](https://github.com/StackExchange/StackExchange.Redis) |[`StackExchange.Redis` guide]({{< relref "/develop/clients/dotnet" >}}) | Yes | +| [C#/.NET](https://learn.microsoft.com/en-us/dotnet/csharp/) | [`NRedisStack`](https://github.com/redis/NRedisStack) |[`NRedisStack` guide]({{< relref "/develop/clients/dotnet/nredisstack" >}}) | Yes | | [JavaScript](https://nodejs.org/en) | [`node-redis`](https://github.com/redis/node-redis) | [`node-redis` guide]({{< relref "/develop/clients/nodejs" >}}) | Yes | | [JavaScript](https://nodejs.org/en) | [`ioredis`](https://github.com/redis/ioredis) | [`ioredis` guide]({{< relref "/develop/clients/ioredis" >}}) | Yes | | [Java](https://www.java.com/en/) | [`Jedis`](https://github.com/redis/jedis) | [`Jedis` guide]({{< relref "/develop/clients/jedis" >}}) | Yes | @@ -113,8 +114,14 @@ between the options for each language. ### C# -- [`NRedisStack`](https://github.com/redis/NRedisStack) is the recommended C# client - library for most use cases. +- [`StackExchange.Redis`](https://github.com/StackExchange/StackExchange.Redis) is the + recommended C# client library for using the core Redis data types and commands. +- [`NRedisStack`](https://github.com/redis/NRedisStack) builds upon + `StackExchange.Redis` with + support for an extended set of data types and features, such as + [JSON]({{< relref "/develop/data-types/json" >}}), + [Redis search]({{< relref "/develop/ai/search-and-query" >}}), and + [Time series]({{< relref "/develop/data-types/timeseries" >}}). - [RedisOM for .NET](https://github.com/redis/redis-om-dotnet) is an object mapping library that provides a high-level API for working with Redis data structures. @@ -199,9 +206,26 @@ questions: nextQuestion: phpLowLevelQuestion dotnet: value: "C#" + nextQuestion: dotnetLowLevelQuestion + + dotnetLowLevelQuestion: + text: | + Do you need Redis Stack features such as JSON, + Search, vector search, or Time series? + whyAsk: | + StackExchange.Redis is the recommended client for core Redis commands, + while NRedisStack extends it with support for Redis Stack data types and features + answers: + yes: + value: "Yes" outcome: label: Use NRedisStack - id: nredisStackOutcome + id: nRedisStackOutcome + no: + value: "No" + outcome: + label: Use StackExchange.Redis + id: stackExchangeRedisOutcome pythonLowLevelQuestion: text: | @@ -285,4 +309,4 @@ questions: outcome: label: Use Predis id: predisOutcome -``` \ No newline at end of file +``` diff --git a/content/develop/clients/dotnet/_index.md b/content/develop/clients/dotnet/_index.md index 8249ce2eec..04d3cfeb10 100644 --- a/content/develop/clients/dotnet/_index.md +++ b/content/develop/clients/dotnet/_index.md @@ -11,67 +11,61 @@ categories: - kubernetes - clients description: Connect your .NET application to a Redis database -linkTitle: NRedisStack (C#/.NET) -title: NRedisStack guide (C#/.NET) +linkTitle: StackExchange.Redis (C#/.NET) +title: StackExchange.Redis guide (C#/.NET) weight: 3 --- -[NRedisStack](https://github.com/redis/NRedisStack) is the .NET client for Redis. -The sections below explain how to install `NRedisStack` and connect your application -to a Redis database. +[StackExchange.Redis](https://github.com/StackExchange/StackExchange.Redis) is the main +.NET client for Redis. It provides an API for the core Redis data types and commands. +A separate library, +[NRedisStack](https://github.com/redis/NRedisStack), builds upon `StackExchange.Redis` with +support for an extended set of data types and features, such as [JSON]({{< relref "/develop/data-types/json" >}}), +[Redis search]({{< relref "/develop/ai/search-and-query" >}}), +[probabilistic data types]({{< relref "/develop/data-types/probabilistic" >}}), and +[Time series]({{< relref "/develop/data-types/timeseries" >}}). -`NRedisStack` requires a running Redis server. See [here]({{< relref "/operate/oss_and_stack/install/" >}}) for Redis Open Source installation instructions. +The sections below explain how to install `StackExchange.Redis` and connect your application +to a Redis database. See the [NRedisStack guide]({{< relref "/develop/clients/dotnet/nredisstack" >}}) for information about installing and using `NRedisStack` to access the extended feature set. +`StackExchange.Redis` requires a running Redis server. See [here]({{< relref "/operate/oss_and_stack/install/" >}}) for Redis Open Source installation instructions. + +{{< note >}} You can also access Redis with an object-mapping client interface. See [Redis OM for .NET]({{< relref "/integrate/redisom-for-net" >}}) for more information. +{{< /note >}} ## Install Using the `dotnet` CLI, run: ```bash -dotnet add package NRedisStack +dotnet add package StackExchange.Redis ``` ## Connect and test Add the following imports to your source file: -{{< clients-example set="landing" step="import" lang_filter="C#-Sync,C#-Async" description="Foundational: Import required NRedisStack namespaces for Redis client functionality" difficulty="beginner" >}} +{{< clients-example set="landing" step="import" lang_filter="C#-Sync (SE.Redis),C#-Async (SE.Redis)" description="Foundational: Import required SE.Redis namespaces for Redis client functionality" difficulty="beginner" >}} {{< /clients-example >}} Connect to localhost on port 6379. The client supports both synchronous and asynchronous commands. -{{< clients-example set="landing" step="connect" lang_filter="C#-Sync,C#-Async" description="Foundational: Connect to a Redis server and establish a client connection" difficulty="beginner" >}} +{{< clients-example set="landing" step="connect" lang_filter="C#-Sync (SE.Redis),C#-Async (SE.Redis)" description="Foundational: Connect to a Redis server and establish a client connection" difficulty="beginner" >}} {{< /clients-example >}} You can test the connection by storing and retrieving a simple string. -{{< clients-example set="landing" step="set_get_string" lang_filter="C#-Sync,C#-Async" description="Foundational: Set and retrieve string values using SET and GET commands" difficulty="beginner" >}} +{{< clients-example set="landing" step="set_get_string" lang_filter="C#-Sync (SE.Redis),C#-Async (SE.Redis)" description="Foundational: Set and retrieve string values using SET and GET commands" difficulty="beginner" >}} {{< /clients-example >}} Store and retrieve a HashMap. -{{< clients-example set="landing" step="set_get_hash" lang_filter="C#-Sync,C#-Async" description="Foundational: Store and retrieve hash data structures using HSET and HGETALL" difficulty="beginner" >}} +{{< clients-example set="landing" step="set_get_hash" lang_filter="C#-Sync (SE.Redis),C#-Async (SE.Redis)" description="Foundational: Store and retrieve hash data structures using HSET and HGETALL" difficulty="beginner" >}} {{< /clients-example >}} -## Redis Open Source modules - -To access Redis Open Source capabilities, use the appropriate interface like this: - -```cs -IBloomCommands bf = db.BF(); -ICuckooCommands cf = db.CF(); -ICmsCommands cms = db.CMS(); -IGraphCommands graph = db.GRAPH(); -ITopKCommands topk = db.TOPK(); -ITdigestCommands tdigest = db.TDIGEST(); -ISearchCommands ft = db.FT(); -IJsonCommands json = db.JSON(); -ITimeSeriesCommands ts = db.TS(); -``` - ## More information See the other pages in this section for more information and examples. diff --git a/content/develop/clients/dotnet/condexec.md b/content/develop/clients/dotnet/condexec.md index f601e06ce1..53df3db597 100644 --- a/content/develop/clients/dotnet/condexec.md +++ b/content/develop/clients/dotnet/condexec.md @@ -9,7 +9,7 @@ categories: - oss - kubernetes - clients -description: Understand how `NRedisStack` uses conditional execution +description: Understand how `StackExchange.Redis` uses conditional execution. linkTitle: Conditional execution title: Conditional execution weight: 60 @@ -18,12 +18,12 @@ weight: 60 Most Redis client libraries use transactions with the [`WATCH`]({{< relref "/commands/watch" >}}) command as the main way to prevent two clients writing to the same key at once (see [Transactions]({{< relref "develop/using-commands/transactions" >}}) for more information). Unfortunately, this approach is -difficult to use explicitly in `NRedisStack`. Its +difficult to use explicitly in `StackExchange.Redis`. Its [multiplexing]({{< relref "/develop/clients/pools-and-muxing" >}}) system is highly efficient and convenient but can also cause bad interactions when different connections use watched transactions at the same time. -Instead, `NRedisStack` relies more heavily on conditional execution. This comes +Instead, `StackExchange.Redis` relies more heavily on conditional execution. This comes in two basic forms, `When` conditions and transaction conditions, both of which are explained in the sections below. @@ -35,7 +35,7 @@ example, the [`SET`]({{< relref "/commands/set" >}}) command has the variants [`SETEX`]({{< relref "/commands/setex" >}}) (set when the key exists), and [`SETNX`]({{< relref "/commands/setnx" >}}) (set when the key doesn't exist). -Instead of providing the different variants of these commands, `NRedisStack` +Instead of providing the different variants of these commands, `StackExchange.Redis` lets you add a `When` condition to the basic command to access its variants. The following example demonstrates this for the [`HashSet()`]({{< relref "/commands/hset" >}}) command. @@ -61,7 +61,7 @@ The available conditions are `When.Exists`, `When.NotExists`, and the default ## Transaction conditions -`NRedisStack` also supports a more extensive set of conditions that you +`StackExchange.Redis` also supports a more extensive set of conditions that you can add to transactions. They are implemented internally using [`WATCH`]({{< relref "/commands/watch" >}}) commands in a way that is guaranteed to be safe, without interactions between different clients. diff --git a/content/develop/clients/dotnet/connect.md b/content/develop/clients/dotnet/connect.md index 50f99a0d5b..03405becd7 100644 --- a/content/develop/clients/dotnet/connect.md +++ b/content/develop/clients/dotnet/connect.md @@ -24,8 +24,6 @@ form "hostname:port" to the `Connect()` method (for example, username, password, and many other options: ```csharp -using NRedisStack; -using NRedisStack.RedisStackCommands; using StackExchange.Redis; ConfigurationOptions conf = new ConfigurationOptions { @@ -139,9 +137,9 @@ to manage open connections carefully to avoid this. Several other Redis client libraries use *connection pools* to reuse a set of open -connections efficiently. NRedisStack uses a different approach called +connections efficiently. StackExchange.Redis uses a different approach called *multiplexing*, which sends all client commands and responses over a -single connection. NRedisStack manages multiplexing for you automatically. +single connection. StackExchange.Redis manages multiplexing for you automatically. This gives high performance without requiring any extra coding. See [Connection pools and multiplexing]({{< relref "/develop/clients/pools-and-muxing" >}}) diff --git a/content/develop/clients/dotnet/error-handling.md b/content/develop/clients/dotnet/error-handling.md index cc8958e8eb..9439845de2 100644 --- a/content/develop/clients/dotnet/error-handling.md +++ b/content/develop/clients/dotnet/error-handling.md @@ -1,6 +1,6 @@ --- title: Error handling -description: Learn how to handle errors when using NRedisStack. +description: Learn how to handle errors when using StackExchange.Redis. linkTitle: Error handling scope: implementation relatedPages: @@ -12,7 +12,10 @@ topics: weight: 60 --- -NRedisStack uses **exceptions** to signal errors. Code examples in the documentation often omit error handling for brevity, but it is essential in production code. This page explains how NRedisStack's error handling works and how to apply common error handling patterns. +`StackExchange.Redis` uses **exceptions** to signal errors. Code examples in the +documentation often omit error handling for brevity, but it is essential in production code. +This page explains how error handling works in `StackExchange.Redis` and how to apply common +error handling patterns. For an overview of error types and handling strategies, see [Error handling]({{< relref "/develop/clients/error-handling" >}}). See also [Production usage]({{< relref "/develop/clients/dotnet/produsage" >}}) @@ -21,7 +24,7 @@ app reliability. ## Exception types -NRedisStack throws exceptions to signal errors. Common exception types include: +`StackExchange.Redis` throws exceptions to signal errors. Common exception types include: | Exception | When it occurs | Recoverable | Recommended action | |---|---|---|---| @@ -37,7 +40,7 @@ for a more detailed discussion of these errors and their causes. The [Error handling]({{< relref "/develop/clients/error-handling" >}}) overview describes four main patterns. The sections below show how to implement them in -NRedisStack: +`StackExchange.Redis`: ### Pattern 1: Fail fast @@ -46,7 +49,6 @@ Catch specific exceptions that represent unrecoverable errors and re-throw them for a full description): ```csharp -using NRedisStack; using StackExchange.Redis; var muxer = ConnectionMultiplexer.Connect("localhost:6379"); @@ -104,7 +106,7 @@ for (int attempt = 0; attempt < maxRetries; attempt++) { ``` See also [Timeouts]({{< relref "/develop/clients/dotnet/produsage#timeouts" >}}) -for more information on configuring timeouts in NRedisStack. +for more information on configuring timeouts in `StackExchange.Redis`. ### Pattern 4: Log and continue @@ -127,7 +129,6 @@ Error handling works the usual way with `async`/`await`, as shown in the example below: ```csharp -using NRedisStack; using StackExchange.Redis; var muxer = ConnectionMultiplexer.Connect("localhost:6379"); diff --git a/content/develop/clients/dotnet/nredisstack/_index.md b/content/develop/clients/dotnet/nredisstack/_index.md new file mode 100644 index 0000000000..a96377fea0 --- /dev/null +++ b/content/develop/clients/dotnet/nredisstack/_index.md @@ -0,0 +1,57 @@ +--- +aliases: /develop/connect/clients/dotnet +categories: +- docs +- develop +- stack +- oss +- rs +- rc +- oss +- kubernetes +- clients +description: Access Redis Open Source modules +linkTitle: NRedisStack extensions +title: NRedisStack extensions guide +weight: 30 +--- + +[NRedisStack](https://github.com/redis/NRedisStack) is a library that builds upon [StackExchange.Redis](https://github.com/StackExchange/StackExchange.Redis) and provides an API for the extended set of Redis data types and features, such as [JSON]({{< relref "/develop/data-types/json" >}}), [Redis search]({{< relref "/develop/ai/search-and-query" >}}), +[probabilistic data types]({{< relref "/develop/data-types/probabilistic" >}}), and [Time series]({{< relref "/develop/data-types/timeseries" >}}). +The sections below explain how to install `NRedisStack`. Note that this also installs +`StackExchange.Redis` as a dependency, so you don't need to install it as a separate step. + +`NRedisStack` requires a running Redis server. See [here]({{< relref "/operate/oss_and_stack/install/" >}}) for Redis Open Source installation instructions. + +{{< note >}} +You can also access Redis with an object-mapping client interface. See +[Redis OM for .NET]({{< relref "/integrate/redisom-for-net" >}}) +for more information. +{{< /note >}} + +## Install + +Using the `dotnet` CLI, run: + +```bash +dotnet add package NRedisStack +``` + +## Redis Open Source modules + +To access Redis Open Source capabilities, use the appropriate interface like this: + +```cs +IBloomCommands bf = db.BF(); // Bloom filter commands +ICuckooCommands cf = db.CF(); // Cuckoo filter commands +ICmsCommands cms = db.CMS(); // Count-min sketch commands +ITopKCommands topk = db.TOPK(); // Top-K commands +ITdigestCommands tdigest = db.TDIGEST(); // T-digest commands +ISearchCommands ft = db.FT(); // Redis search commands +IJsonCommands json = db.JSON(); // JSON commands +ITimeSeriesCommands ts = db.TS(); // Time series commands +``` + +## More information + +See the other pages in this section for more information and examples. diff --git a/content/develop/clients/dotnet/prob.md b/content/develop/clients/dotnet/nredisstack/prob.md similarity index 90% rename from content/develop/clients/dotnet/prob.md rename to content/develop/clients/dotnet/nredisstack/prob.md index 50920cf9ed..d5d259c265 100644 --- a/content/develop/clients/dotnet/prob.md +++ b/content/develop/clients/dotnet/nredisstack/prob.md @@ -99,7 +99,7 @@ add. The following example adds some names to a Bloom filter representing a list of users and checks for the presence or absence of users in the list. Note that you must use the `BF()` method to access the Bloom filter commands. -{{< clients-example set="home_prob_dts" step="bloom" lang_filter="C#-Sync" description="Foundational: Use Bloom filters for memory-efficient set membership testing with false positive possibility" difficulty="beginner" >}} +{{< clients-example set="home_prob_dts" step="bloom" lang_filter="C#-Sync (NRedisStack)" description="Foundational: Use Bloom filters for memory-efficient set membership testing with false positive possibility" difficulty="beginner" >}} {{< /clients-example >}} A Cuckoo filter has similar features to a Bloom filter, but also supports @@ -107,7 +107,7 @@ a deletion operation to remove hashes from a set, as shown in the example below. Note that you must use the `CF()` method to access the Cuckoo filter commands. -{{< clients-example set="home_prob_dts" step="cuckoo" lang_filter="C#-Sync" description="Foundational: Use Cuckoo filters for set membership testing with deletion support and faster lookups than Bloom filters" difficulty="beginner" >}} +{{< clients-example set="home_prob_dts" step="cuckoo" lang_filter="C#-Sync (NRedisStack)" description="Foundational: Use Cuckoo filters for set membership testing with deletion support and faster lookups than Bloom filters" difficulty="beginner" >}} {{< /clients-example >}} Which of these two data types you choose depends on your use case. @@ -128,7 +128,7 @@ You can also merge two or more HyperLogLogs to find the cardinality of the [union](https://en.wikipedia.org/wiki/Union_(set_theory)) of the sets they represent. -{{< clients-example set="home_prob_dts" step="hyperloglog" lang_filter="C#-Sync" description="Foundational: Estimate set cardinality with HyperLogLog for memory-efficient counting of distinct items" difficulty="beginner" >}} +{{< clients-example set="home_prob_dts" step="hyperloglog" lang_filter="C#-Sync (NRedisStack)" description="Foundational: Estimate set cardinality with HyperLogLog for memory-efficient counting of distinct items" difficulty="beginner" >}} {{< /clients-example >}} The main benefit that HyperLogLogs offer is their very low @@ -169,7 +169,7 @@ a Count-min sketch object, add data to it, and then query it. Note that you must use the `CMS()` method to access the Count-min sketch commands. -{{< clients-example set="home_prob_dts" step="cms" lang_filter="C#-Sync" description="Foundational: Track approximate item frequencies with Count-min sketch for memory-efficient statistics on data streams" difficulty="intermediate" >}} +{{< clients-example set="home_prob_dts" step="cms" lang_filter="C#-Sync (NRedisStack)" description="Foundational: Track approximate item frequencies with Count-min sketch for memory-efficient statistics on data streams" difficulty="intermediate" >}} {{< /clients-example >}} The advantage of using a CMS over keeping an exact count with a @@ -202,7 +202,7 @@ shows how to merge two or more t-digest objects to query the combined data set. Note that you must use the `TDIGEST()` method to access the t-digest commands. -{{< clients-example set="home_prob_dts" step="tdigest" lang_filter="C#-Sync" description="Foundational: Estimate quantiles and percentiles with t-digest for memory-efficient statistical analysis of large datasets" difficulty="intermediate" >}} +{{< clients-example set="home_prob_dts" step="tdigest" lang_filter="C#-Sync (NRedisStack)" description="Foundational: Estimate quantiles and percentiles with t-digest for memory-efficient statistical analysis of large datasets" difficulty="intermediate" >}} {{< /clients-example >}} A t-digest object also supports several other related commands, such @@ -225,5 +225,5 @@ top *k* items and query whether or not a given item is in the list. Note that you must use the `TOPK()` method to access the Top-K commands. -{{< clients-example set="home_prob_dts" step="topk" lang_filter="C#-Sync" description="Foundational: Track top K most frequent items in a data stream with Top-K for efficient ranking without storing all items" difficulty="intermediate" >}} +{{< clients-example set="home_prob_dts" step="topk" lang_filter="C#-Sync (NRedisStack)" description="Foundational: Track top K most frequent items in a data stream with Top-K for efficient ranking without storing all items" difficulty="intermediate" >}} {{< /clients-example >}} diff --git a/content/develop/clients/dotnet/queryjson.md b/content/develop/clients/dotnet/nredisstack/queryjson.md similarity index 100% rename from content/develop/clients/dotnet/queryjson.md rename to content/develop/clients/dotnet/nredisstack/queryjson.md diff --git a/content/develop/clients/dotnet/vecsearch.md b/content/develop/clients/dotnet/nredisstack/vecsearch.md similarity index 100% rename from content/develop/clients/dotnet/vecsearch.md rename to content/develop/clients/dotnet/nredisstack/vecsearch.md diff --git a/content/develop/clients/dotnet/produsage.md b/content/develop/clients/dotnet/produsage.md index e992821add..631a28c9fc 100644 --- a/content/develop/clients/dotnet/produsage.md +++ b/content/develop/clients/dotnet/produsage.md @@ -9,7 +9,7 @@ categories: - oss - kubernetes - clients -description: Get your NRedisStack app ready for production +description: Get your `StackExchange.Redis` app ready for production linkTitle: Production usage title: Production usage weight: 70 @@ -59,7 +59,6 @@ inform users who try to connect that service is temporarily unavailable rather than letting them run into errors. ```cs -using NRedisStack; using StackExchange.Redis; ConnectionMultiplexer muxer = ConnectionMultiplexer.Connect("localhost:6379"); @@ -74,7 +73,7 @@ muxer.ServerMaintenanceEvent += (object sender, ServerMaintenanceEvent e) => { If a network or server error occurs while your code is opening a connection or issuing a command, it can end up hanging indefinitely. -To prevent this, `NRedisStack` sets timeouts for socket +To prevent this, `StackExchange.Redis` sets timeouts for socket reads and writes and for opening connections. By default, the timeout is five seconds for all operations, but @@ -117,7 +116,7 @@ for more information on handling exceptions. ### Retries -During the initial `ConnectionMultiplexer.Connect()` call, `NRedisStack` will +During the initial `ConnectionMultiplexer.Connect()` call, `StackExchange.Redis` will keep trying to connect if the first attempt fails. By default, it will make three attempts, but you can configure the number of retries using the `ConnectRetry` configuration option: @@ -130,10 +129,10 @@ var muxer = ConnectionMultiplexer.Connect(new ConfigurationOptions { }); ``` -After the initial `Connect()` call is successful, `NRedisStack` will +After the initial `Connect()` call is successful, `StackExchange.Redis` will automatically attempt to reconnect if the connection is lost. You can specify a reconnection strategy with the `ReconnectRetryPolicy` configuration -option. `NRedisStack` provides two built-in classes that implement +option. `StackExchange.Redis` provides two built-in classes that implement reconnection strategies: - `ExponentialRetry`: (Default) Uses an @@ -157,7 +156,7 @@ var muxer = ConnectionMultiplexer.Connect(new ConfigurationOptions { You can also implement your own custom retry policy by creating a class that implements the `IReconnectRetryPolicy` interface. -`NRedisStack` doesn't provide an automated retry mechanism for commands, but +`StackExchange.Redis` doesn't provide an automated retry mechanism for commands, but you can implement your own retry logic in your application code. Use a loop with a `try`/`catch` block to catch `RedisConnectionException` and `RedisTimeoutException` exceptions and then retry the command after a diff --git a/content/develop/clients/dotnet/transpipe.md b/content/develop/clients/dotnet/transpipe.md index 84b3389f85..f0a69cc766 100644 --- a/content/develop/clients/dotnet/transpipe.md +++ b/content/develop/clients/dotnet/transpipe.md @@ -37,7 +37,7 @@ versions of the standard command methods buffered in the pipeline and only execute when you call the `Execute()` method on the pipeline object. -{{< clients-example set="pipe_trans_tutorial" step="basic_pipe" lang_filter="C#-Sync" description="Foundational: Use pipelines to batch multiple commands together and reduce network round trips" difficulty="beginner" >}} +{{< clients-example set="pipe_trans_tutorial" step="basic_pipe" lang_filter="C#-Sync (SE.Redis)" description="Foundational: Use pipelines to batch multiple commands together and reduce network round trips" difficulty="beginner" >}} {{< /clients-example >}} ## Execute a transaction @@ -47,7 +47,7 @@ instance of the `Transaction` class, call async command methods on that object, and then call the transaction object's `Execute()` method to execute it. -{{< clients-example set="pipe_trans_tutorial" step="basic_trans" lang_filter="C#-Sync" description="Foundational: Use transactions to execute multiple commands atomically without interruption from other clients" difficulty="beginner" >}} +{{< clients-example set="pipe_trans_tutorial" step="basic_trans" lang_filter="C#-Sync (SE.Redis)" description="Foundational: Use transactions to execute multiple commands atomically without interruption from other clients" difficulty="beginner" >}} {{< /clients-example >}} ## Watch keys for changes @@ -64,8 +64,8 @@ The approach to optimistic locking that other clients use (adding the [`WATCH`]({{< relref "/commands/watch" >}}) command explicitly to a transaction) doesn't work well with the [multiplexing]({{< relref "/develop/clients/pools-and-muxing" >}}) -system that `NRedisStack` uses. -Instead, `NRedisStack` relies on conditional execution of commands +system that `StackExchange.Redis` uses. +Instead, `StackExchange.Redis` relies on conditional execution of commands to get a similar effect. Use the `AddCondition()` method to abort a transaction if a particular @@ -77,7 +77,7 @@ For example, the `KeyNotExists` condition aborts the transaction if a specified key exists or is added by another client while the transaction executes: -{{< clients-example set="pipe_trans_tutorial" step="trans_watch" lang_filter="C#-Sync" description="Optimistic locking: Use conditions to monitor keys for changes and abort transactions when conflicts occur" difficulty="intermediate" >}} +{{< clients-example set="pipe_trans_tutorial" step="trans_watch" lang_filter="C#-Sync (SE.Redis)" description="Optimistic locking: Use conditions to monitor keys for changes and abort transactions when conflicts occur" difficulty="intermediate" >}} {{< /clients-example >}} You can also use a `When` condition on certain individual commands to diff --git a/content/develop/clients/dotnet/vecsets.md b/content/develop/clients/dotnet/vecsets.md index b56ff35be9..1f549166f4 100644 --- a/content/develop/clients/dotnet/vecsets.md +++ b/content/develop/clients/dotnet/vecsets.md @@ -54,14 +54,14 @@ dotnet add package Microsoft.ML In a new C# file, import the required classes. Note that the `#pragma` directive suppresses warnings about the experimental status of the vector set API: -{{< clients-example set="home_vecsets" step="import" lang_filter="C#-Sync" description="Foundational: Import required libraries for vector sets, embeddings, and Redis operations" difficulty="beginner" >}} +{{< clients-example set="home_vecsets" step="import" lang_filter="C#-Sync (SE.Redis)" description="Foundational: Import required libraries for vector sets, embeddings, and Redis operations" difficulty="beginner" >}} {{< /clients-example >}} ## Access the model Use the `GetPredictionEngine()` helper function declared in the example below to load the model that creates the embeddings: -{{< clients-example set="home_vecsets" step="model" lang_filter="C#-Sync" description="Practical pattern: Initialize a SentenceTransformer model to generate vector embeddings from text" difficulty="beginner" >}} +{{< clients-example set="home_vecsets" step="model" lang_filter="C#-Sync (SE.Redis)" description="Practical pattern: Initialize a SentenceTransformer model to generate vector embeddings from text" difficulty="beginner" >}} {{< /clients-example >}} The `GetPredictionEngine()` function uses two classes, `TextData` and `TransformedTextData`, @@ -69,7 +69,7 @@ to specify the `PredictionEngine` model. These have a very simple definition and are required because the model expects the input and output to be passed in named object fields: -{{< clients-example set="home_vecsets" step="data_classes" lang_filter="C#-Sync" description="Foundational: Define data classes for the embedding model's input and output structures" difficulty="beginner" >}} +{{< clients-example set="home_vecsets" step="data_classes" lang_filter="C#-Sync (SE.Redis)" description="Foundational: Define data classes for the embedding model's input and output structures" difficulty="beginner" >}} {{< /clients-example >}} Note that you must declare these classes at the end of the source file @@ -79,7 +79,7 @@ The `GetEmbedding()` function declared below can then use this model to generate an embedding from a section of text and return it as a `float[]` array, which is the format required by the vector set API: -{{< clients-example set="home_vecsets" step="get_embedding" lang_filter="C#-Sync" description="Foundational: Create a function to generate vector embeddings from text using the prediction engine" difficulty="beginner" >}} +{{< clients-example set="home_vecsets" step="get_embedding" lang_filter="C#-Sync (SE.Redis)" description="Foundational: Create a function to generate vector embeddings from text using the prediction engine" difficulty="beginner" >}} {{< /clients-example >}} ## Create the data @@ -87,7 +87,7 @@ which is the format required by the vector set API: The example data is contained a `Dictionary` object with some brief descriptions of famous people: -{{< clients-example set="home_vecsets" step="data" lang_filter="C#-Sync" description="Foundational: Define sample data with text descriptions for vector embedding and storage" difficulty="beginner" >}} +{{< clients-example set="home_vecsets" step="data" lang_filter="C#-Sync (SE.Redis)" description="Foundational: Define sample data with text descriptions for vector embedding and storage" difficulty="beginner" >}} {{< /clients-example >}} ## Add the data to a vector set @@ -105,7 +105,7 @@ The call to `VectorSetAdd()` also adds the `born` and `died` values from the original dictionary as attribute data. You can access this during a query or by using the [`VectorSetGetAttributesJson()`]({{< relref "/commands/vgetattr" >}}) method. -{{< clients-example set="home_vecsets" step="add_data" lang_filter="C#-Sync" description="Foundational: Add vector embeddings and attributes to a vector set using VADD command" difficulty="beginner" >}} +{{< clients-example set="home_vecsets" step="add_data" lang_filter="C#-Sync (SE.Redis)" description="Foundational: Add vector embeddings and attributes to a vector set using VADD command" difficulty="beginner" >}} {{< /clients-example >}} ## Query the vector set @@ -118,7 +118,7 @@ return elements of the set, ranked in order of similarity to the query. Start with a simple query for "actors": -{{< clients-example set="home_vecsets" step="basic_query" lang_filter="C#-Sync" description="Vector similarity search: Find semantically similar items in a vector set using VSIM command" difficulty="intermediate" >}} +{{< clients-example set="home_vecsets" step="basic_query" lang_filter="C#-Sync (SE.Redis)" description="Vector similarity search: Find semantically similar items in a vector set using VSIM command" difficulty="intermediate" >}} {{< /clients-example >}} This returns the following list of elements (formatted slightly for clarity): @@ -137,7 +137,7 @@ on the information contained in the embedding model. You can use the `Count` property of `VectorSetSimilaritySearchRequest` to limit the list of elements to just the most relevant few items: -{{< clients-example set="home_vecsets" step="limited_query" lang_filter="C#-Sync" description="Vector similarity search with limits: Restrict results to the top K most similar items using the count parameter" difficulty="intermediate" >}} +{{< clients-example set="home_vecsets" step="limited_query" lang_filter="C#-Sync (SE.Redis)" description="Vector similarity search with limits: Restrict results to the top K most similar items using the count parameter" difficulty="intermediate" >}} {{< /clients-example >}} The reason for using text embeddings rather than simple text search @@ -147,7 +147,7 @@ different. For example, the word "entertainer" doesn't appear in any of the descriptions but if you use it as a query, the actors and musicians are ranked highest in the results list: -{{< clients-example set="home_vecsets" step="entertainer_query" lang_filter="C#-Sync" description="Semantic search: Leverage text embeddings to find semantically similar items even when exact keywords don't match" difficulty="intermediate" >}} +{{< clients-example set="home_vecsets" step="entertainer_query" lang_filter="C#-Sync (SE.Redis)" description="Semantic search: Leverage text embeddings to find semantically similar items even when exact keywords don't match" difficulty="intermediate" >}} {{< /clients-example >}} Similarly, if you use "science" as a query, you get the following results: @@ -168,7 +168,7 @@ with `VectorSetSimilaritySearch()` to restrict the search further. For example, repeat the "science" query, but this time limit the results to people who died before the year 2000: -{{< clients-example set="home_vecsets" step="filtered_query" lang_filter="C#-Sync" description="Filtered vector search: Combine vector similarity with attribute filters to narrow results based on metadata conditions" difficulty="advanced" >}} +{{< clients-example set="home_vecsets" step="filtered_query" lang_filter="C#-Sync (SE.Redis)" description="Filtered vector search: Combine vector similarity with attribute filters to narrow results based on metadata conditions" difficulty="advanced" >}} {{< /clients-example >}} Note that the boolean filter expression is applied to items in the list @@ -186,7 +186,7 @@ docs for more information and code examples. See the about text embeddings and other AI techniques you can use with Redis. You may also be interested in -[vector search]({{< relref "/develop/clients/dotnet/vecsearch" >}}). +[vector search]({{< relref "/develop/clients/dotnet/nredisstack/vecsearch" >}}). This is a feature of [Redis Search]({{< relref "/develop/ai/search-and-query" >}}) that lets you retrieve diff --git a/content/develop/clients/error-handling.md b/content/develop/clients/error-handling.md index bb563802d7..27bd234e15 100644 --- a/content/develop/clients/error-handling.md +++ b/content/develop/clients/error-handling.md @@ -389,4 +389,4 @@ For detailed information about exceptions in your client library, see: - [Node.js error handling]({{< relref "/develop/clients/nodejs/error-handling" >}}) - [Java (Jedis) error handling]({{< relref "/develop/clients/jedis/error-handling" >}}) - [Go (go-redis) error handling]({{< relref "/develop/clients/go/error-handling" >}}) -- [.NET (NRedisStack) error handling]({{< relref "/develop/clients/dotnet/error-handling" >}}) +- [.NET (StackExchange.Redis) error handling]({{< relref "/develop/clients/dotnet/error-handling" >}}) diff --git a/content/develop/clients/pools-and-muxing.md b/content/develop/clients/pools-and-muxing.md index 821b76f3c4..fc39e5557b 100644 --- a/content/develop/clients/pools-and-muxing.md +++ b/content/develop/clients/pools-and-muxing.md @@ -31,7 +31,7 @@ The [`redis-py`]({{< relref "/develop/clients/redis-py" >}}), [`jedis`]({{< relref "/develop/clients/jedis" >}}), and [`go-redis`]({{< relref "/develop/clients/go" >}}) clients support connection pooling, while -[`NRedisStack`]({{< relref "/develop/clients/dotnet" >}}) +[`StackExchange.Redis`]({{< relref "/develop/clients/dotnet" >}}) supports multiplexing. [`Lettuce`]({{< relref "/develop/clients/lettuce" >}}) supports both approaches. diff --git a/content/develop/get-started/vector-database.md b/content/develop/get-started/vector-database.md index 073369c531..6f7782ada6 100644 --- a/content/develop/get-started/vector-database.md +++ b/content/develop/get-started/vector-database.md @@ -31,7 +31,7 @@ vector processing. You may also be interested in the vector query examples for our other client libraries: - [`redis-py` (Python)]({{< relref "/develop/clients/redis-py/vecsearch" >}}) -- [`NRedisStack`(C#/.NET)]({{< relref "/develop/clients/dotnet/vecsearch" >}}) +- [`NRedisStack`(C#/.NET)]({{< relref "/develop/clients/dotnet/nredisstack/vecsearch" >}}) - [`node-redis` (JavaScript/Node.js)]({{< relref "/develop/clients/nodejs/vecsearch" >}}) - [`jedis` (Java)]({{< relref "/develop/clients/jedis/vecsearch" >}}) - [`go-redis` (Go)]({{< relref "/develop/clients/go/vecsearch" >}}) diff --git a/content/develop/whats-new/_index.md b/content/develop/whats-new/_index.md index c66c1308e1..3cdb3e52da 100644 --- a/content/develop/whats-new/_index.md +++ b/content/develop/whats-new/_index.md @@ -255,7 +255,7 @@ weight: 10 - [Enhanced time series examples]({{< relref "/develop/data-types/timeseries/_index" >}}) with query and aggregation info - Added testable code examples (TCE) support - Probabilistic: - - Added testable examples for [Python]({{< relref "/develop/clients/redis-py/prob/" >}}), [C#]({{< relref "/develop/clients/dotnet/prob/" >}}), [Java]({{< relref "/develop/clients/jedis/prob/" >}}), and [Go]({{< relref "/develop/clients/go/prob/" >}}) + - Added testable examples for [Python]({{< relref "/develop/clients/redis-py/prob/" >}}), [C#]({{< relref "/develop/clients/dotnet/nredisstack/prob/" >}}), [Java]({{< relref "/develop/clients/jedis/prob/" >}}), and [Go]({{< relref "/develop/clients/go/prob/" >}}) - Updated [Cuckoo filter documentation]({{< relref "/develop/data-types/probabilistic/cuckoo-filter" >}}) --- @@ -277,9 +277,9 @@ weight: 10 - Added [command reliability information]({{< relref "/develop/clients/nodejs/produsage#command-execution-reliability" >}}) - Fixed [reconnection details]({{< relref "/develop/clients/nodejs/connect#reconnect-after-disconnection" >}}) -#### .NET (NRedisStack) +#### .NET (StackExchange.Redis/NRedisStack) - Added [retries and timeouts]({{< relref "/develop/clients/dotnet/produsage" >}}) to production usage advice -- Enhanced [dialect 2 notes]({{< relref "/develop/clients/dotnet/queryjson" >}}) +- Enhanced [dialect 2 notes]({{< relref "/develop/clients/dotnet/nredisstack/queryjson" >}}) #### Go (go-redis) - Added [retries and timeouts]({{< relref "/develop/clients/go/produsage" >}}) to production usage @@ -331,7 +331,7 @@ weight: 10 - [Node.js]({{< relref "/develop/clients/nodejs/vecsearch.md" >}}) - [Java (Jedis)]({{< relref "/develop/clients/jedis/vecsearch.md" >}}) - [Go]({{< relref "/develop/clients/go/vecsearch.md" >}}) - - [.NET]({{< relref "/develop/clients/dotnet/vecsearch.md" >}}) + - [.NET]({{< relref "/develop/clients/dotnet/nredisstack/vecsearch" >}}) - Updated AI integrations: - [AI overview]({{< relref "/develop/ai/index.md" >}}) - [RAG intro]({{< relref "/develop/get-started/rag.md" >}}) @@ -388,9 +388,9 @@ weight: 10 - [JSON queries]({{< relref "/develop/clients/go/queryjson.md" >}}) #### .NET -- [Vector search]({{< relref "/develop/clients/dotnet/vecsearch.md" >}}) -- [Trans/pipe usage]({{< relref "/develop/clients/dotnet/transpipe.md" >}}) -- [JSON queries]({{< relref "/develop/clients/dotnet/queryjson.md" >}}) +- [Vector search]({{< relref "/develop/clients/dotnet/nredisstack/vecsearch" >}}) +- [Trans/pipe usage]({{< relref "/develop/clients/dotnet/transpipe" >}}) +- [JSON queries]({{< relref "/develop/clients/dotnet/nredisstack/queryjson" >}}) #### Java (Jedis) - [Vector search]({{< relref "/develop/clients/jedis/vecsearch.md" >}}) diff --git a/content/integrate/NRedisStack/_index.md b/content/integrate/NRedisStack/_index.md index 275ca4d39a..76d7a13e80 100644 --- a/content/integrate/NRedisStack/_index.md +++ b/content/integrate/NRedisStack/_index.md @@ -1,5 +1,5 @@ --- -LinkTitle: NRedisStack +LinkTitle: StackExchange.Redis Title: C#/.NET client for Redis categories: - docs @@ -10,24 +10,23 @@ categories: description: Learn how to build with Redis and C#/.NET group: library stack: true -summary: NRedisStack is a C#/.NET library for Redis. -title: NRedisStack +summary: StackExchange.Redis is a C#/.NET library for Redis. +title: StackExchange.Redis type: integration weight: 2 --- -Connect your C#/.NET application to a Redis database using the NRedisStack client library. +Connect your C#/.NET application to a Redis database using the StackExchange.Redis client library. ## Overview -NRedisStack is a comprehensive .NET client library for Redis that extends StackExchange.Redis with support for all Redis data structures and capabilities. It provides strongly-typed APIs for Redis data structures and advanced features, making it ideal for modern .NET applications. +StackExchange.Redis is a .NET client library for Redis. It provides strongly-typed APIs for Redis +data structures and advanced features, making it ideal for modern .NET applications. ## Key Features -- **Redis Stack (v7.4 and earlier) and Redis 8 support**: Native support for JSON, time series, and probabilistic data structures, and Redis Search. - **Strongly Typed**: Type-safe APIs with full IntelliSense support in Visual Studio - **Async/Await**: Native asynchronous programming support for high-performance applications -- **StackExchange.Redis Integration**: Built on the proven StackExchange.Redis foundation - **Connection Multiplexing**: Efficient connection sharing across multiple operations - **Cluster Support**: Full Redis Cluster support for distributed deployments - **Pipeline Support**: Command batching for improved throughput @@ -35,4 +34,4 @@ NRedisStack is a comprehensive .NET client library for Redis that extends StackE ## Getting Started -Refer to the complete [C#/.NET guide]({{< relref "/develop/clients/dotnet" >}}) to install, connect, and use NRedisStack. +Refer to the complete [C#/.NET guide]({{< relref "/develop/clients/dotnet" >}}) to install, connect, and use StackExchange.Redis. diff --git a/content/integrate/redis-ai-libraries/_index.md b/content/integrate/redis-ai-libraries/_index.md index 7162fe2054..23a0d25932 100644 --- a/content/integrate/redis-ai-libraries/_index.md +++ b/content/integrate/redis-ai-libraries/_index.md @@ -61,7 +61,7 @@ All major Redis client libraries support vector search operations: - **redis-py (Python)**: [Vector search guide]({{< relref "/develop/clients/redis-py/vecsearch" >}}) - **node-redis (JavaScript)**: [Vector search guide]({{< relref "/develop/clients/nodejs/vecsearch" >}}) - **Jedis (Java)**: [Vector search guide]({{< relref "/develop/clients/jedis/vecsearch" >}}) -- **NRedisStack (C#/.NET)**: [Vector search guide]({{< relref "/develop/clients/dotnet/vecsearch" >}}) +- **NRedisStack (C#/.NET)**: [Vector search guide]({{< relref "/develop/clients/dotnet/nredisstack/vecsearch" >}}) - **go-redis (Go)**: [Vector search guide]({{< relref "/develop/clients/go/vecsearch" >}}) ## Getting Started diff --git a/content/operate/rc/databases/connect/_index.md b/content/operate/rc/databases/connect/_index.md index d5e9ca7edf..4d70a1edee 100644 --- a/content/operate/rc/databases/connect/_index.md +++ b/content/operate/rc/databases/connect/_index.md @@ -85,7 +85,7 @@ A Redis client is a software library or tool that enables applications to intera The connection wizard provides code snippets to connect to your database with the following programming languages: -- .NET using [NRedisStack]({{< relref "/develop/clients/dotnet" >}}) +- .NET using [StackExchange.Redis/NRedisStack]({{< relref "/develop/clients/dotnet" >}}) - node.js using [node-redis]({{< relref "/develop/clients/nodejs" >}}) - Python using [redis-py]({{< relref "/develop/clients/redis-py" >}}) - Java using [Jedis]({{< relref "/develop/clients/jedis" >}}) and [Lettuce]({{< relref "/develop/clients/lettuce" >}}) diff --git a/content/operate/rc/rc-quickstart.md b/content/operate/rc/rc-quickstart.md index b331445f06..d2083181de 100644 --- a/content/operate/rc/rc-quickstart.md +++ b/content/operate/rc/rc-quickstart.md @@ -146,7 +146,7 @@ A Redis client is a software library or tool that enables applications to intera The connection wizard provides code snippets to connect to your database with the following programming languages: -- .NET using [NRedisStack]({{< relref "/develop/clients/dotnet" >}}) +- .NET using [StackExchange.Redis/NRedisStack]({{< relref "/develop/clients/dotnet" >}}) - node.js using [node-redis]({{< relref "/develop/clients/nodejs" >}}) - Python using [redis-py]({{< relref "/develop/clients/redis-py" >}}) - Java using [Jedis]({{< relref "/develop/clients/jedis" >}}) and [Lettuce]({{< relref "/develop/clients/lettuce" >}}) diff --git a/content/operate/rc/resilient-apps.md b/content/operate/rc/resilient-apps.md index d45c4c0556..3907f2dc7b 100644 --- a/content/operate/rc/resilient-apps.md +++ b/content/operate/rc/resilient-apps.md @@ -79,7 +79,7 @@ For production-ready configurations and best practices, see the production usage - [Jedis]({{< relref "/develop/clients/jedis/produsage" >}}) - [Lettuce]({{< relref "/develop/clients/lettuce/produsage" >}}) - [go-redis]({{< relref "/develop/clients/go/produsage" >}}) -- [NRedisStack]({{< relref "/develop/clients/dotnet/produsage" >}}) +- [StackExchange.Redis]({{< relref "/develop/clients/dotnet/produsage" >}}) ### Re-attempt connections diff --git a/content/operate/rs/7.22/databases/connect/supported-clients-browsers.md b/content/operate/rs/7.22/databases/connect/supported-clients-browsers.md index 079b44c049..773082e5bd 100644 --- a/content/operate/rs/7.22/databases/connect/supported-clients-browsers.md +++ b/content/operate/rs/7.22/databases/connect/supported-clients-browsers.md @@ -30,7 +30,7 @@ Note: You cannot use client libraries to configure Redis Enterprise Software. I We recommend the following clients when using a [discovery service]({{< relref "/operate/rs/7.22/databases/durability-ha/discovery-service.md" >}}) based on the Redis Sentinel API: - [redis-py]({{< relref "/develop/clients/redis-py" >}}) (Python client) -- [NRedisStack]({{< relref "/develop/clients/dotnet" >}}) (.NET client) +- [StackExchange.Redis]({{< relref "/develop/clients/dotnet" >}}) (.NET client) - [Jedis]({{< relref "/develop/clients/jedis" >}}) (synchronous Java client) - [Lettuce]({{< relref "/develop/clients/lettuce" >}}) (asynchronous Java client) - [go-redis]({{< relref "/develop/clients/go" >}}) (Go client) diff --git a/content/operate/rs/7.22/references/client_references/_index.md b/content/operate/rs/7.22/references/client_references/_index.md index 1a0d04ea33..09edbdda9d 100644 --- a/content/operate/rs/7.22/references/client_references/_index.md +++ b/content/operate/rs/7.22/references/client_references/_index.md @@ -19,7 +19,7 @@ To connect to Redis instances from within your application, use a Redis client l | Language | Client name | | :---------- | :------------- | -| .Net | [NRedisStack]({{< relref "/develop/clients/dotnet" >}}) | +| .Net | [StackExchange.Redis]({{< relref "/develop/clients/dotnet" >}}) | | Go | [go-redis]({{< relref "/develop/clients/go" >}}) | | Java | [Jedis]({{< relref "/develop/clients/jedis" >}}) (Synchronous) and [Lettuce]({{< relref "/develop/clients/lettuce" >}}) (Asynchronous) | | Node.js | [node-redis]({{< relref "/develop/clients/nodejs" >}}) | diff --git a/content/operate/rs/7.4/databases/connect/supported-clients-browsers.md b/content/operate/rs/7.4/databases/connect/supported-clients-browsers.md index 52ec92b39d..a97643f579 100644 --- a/content/operate/rs/7.4/databases/connect/supported-clients-browsers.md +++ b/content/operate/rs/7.4/databases/connect/supported-clients-browsers.md @@ -30,7 +30,7 @@ Note: You cannot use client libraries to configure Redis Enterprise Software. I We recommend the following clients when using a [discovery service]({{< relref "/operate/rs/7.4/databases/durability-ha/discovery-service.md" >}}) based on the Redis Sentinel API: - [redis-py]({{< relref "/develop/clients/redis-py" >}}) (Python client) -- [NRedisStack]({{< relref "/develop/clients/dotnet" >}}) (.NET client) +- [StackExchange.Redis]({{< relref "/develop/clients/dotnet" >}}) (.NET client) - [Jedis]({{< relref "/develop/clients/jedis" >}}) (synchronous Java client) - [Lettuce]({{< relref "/develop/clients/lettuce" >}}) (asynchronous Java client) - [go-redis]({{< relref "/develop/clients/go" >}}) (Go client) diff --git a/content/operate/rs/7.4/references/client_references/_index.md b/content/operate/rs/7.4/references/client_references/_index.md index 1218fa925a..38ae158df9 100644 --- a/content/operate/rs/7.4/references/client_references/_index.md +++ b/content/operate/rs/7.4/references/client_references/_index.md @@ -19,7 +19,7 @@ To connect to Redis instances from within your application, use a Redis client l | Language | Client name | | :---------- | :------------- | -| .Net | [NRedisStack]({{< relref "/develop/clients/dotnet" >}}) | +| .Net | [StackExchange.Redis]({{< relref "/develop/clients/dotnet" >}}) | | Go | [go-redis]({{< relref "/develop/clients/go" >}}) | | Java | [Jedis]({{< relref "/develop/clients/jedis" >}}) (Synchronous) and [Lettuce]({{< relref "/develop/clients/lettuce" >}}) (Asynchronous) | | Node.js | [node-redis]({{< relref "/develop/clients/nodejs" >}}) | diff --git a/content/operate/rs/7.8/databases/connect/supported-clients-browsers.md b/content/operate/rs/7.8/databases/connect/supported-clients-browsers.md index 2206450898..aa5235ec2e 100644 --- a/content/operate/rs/7.8/databases/connect/supported-clients-browsers.md +++ b/content/operate/rs/7.8/databases/connect/supported-clients-browsers.md @@ -30,7 +30,7 @@ Note: You cannot use client libraries to configure Redis Enterprise Software. I We recommend the following clients when using a [discovery service]({{< relref "/operate/rs/7.8/databases/durability-ha/discovery-service.md" >}}) based on the Redis Sentinel API: - [redis-py]({{< relref "/develop/clients/redis-py" >}}) (Python client) -- [NRedisStack]({{< relref "/develop/clients/dotnet" >}}) (.NET client) +- [StackExchange.Redis]({{< relref "/develop/clients/dotnet" >}}) (.NET client) - [Jedis]({{< relref "/develop/clients/jedis" >}}) (synchronous Java client) - [Lettuce]({{< relref "/develop/clients/lettuce" >}}) (asynchronous Java client) - [go-redis]({{< relref "/develop/clients/go" >}}) (Go client) diff --git a/content/operate/rs/7.8/references/client_references/_index.md b/content/operate/rs/7.8/references/client_references/_index.md index ccb0207724..b6d4798cb2 100644 --- a/content/operate/rs/7.8/references/client_references/_index.md +++ b/content/operate/rs/7.8/references/client_references/_index.md @@ -19,7 +19,7 @@ To connect to Redis instances from within your application, use a Redis client l | Language | Client name | | :---------- | :------------- | -| .Net | [NRedisStack]({{< relref "/develop/clients/dotnet" >}}) | +| .Net | [StackExchange.Redis]({{< relref "/develop/clients/dotnet" >}}) | | Go | [go-redis]({{< relref "/develop/clients/go" >}}) | | Java | [Jedis]({{< relref "/develop/clients/jedis" >}}) (Synchronous) and [Lettuce]({{< relref "/develop/clients/lettuce" >}}) (Asynchronous) | | Node.js | [node-redis]({{< relref "/develop/clients/nodejs" >}}) | diff --git a/content/operate/rs/databases/connect/supported-clients-browsers.md b/content/operate/rs/databases/connect/supported-clients-browsers.md index c28129d595..9fb9d92b60 100644 --- a/content/operate/rs/databases/connect/supported-clients-browsers.md +++ b/content/operate/rs/databases/connect/supported-clients-browsers.md @@ -29,7 +29,7 @@ Note: You cannot use client libraries to configure Redis Software. Instead, use We recommend the following clients when using a [discovery service]({{< relref "/operate/rs/databases/durability-ha/discovery-service.md" >}}) based on the Redis Sentinel API: - [redis-py]({{< relref "/develop/clients/redis-py" >}}) (Python client) -- [NRedisStack]({{< relref "/develop/clients/dotnet" >}}) (.NET client) +- [StackExchange.Redis]({{< relref "/develop/clients/dotnet" >}}) (.NET client) - [Jedis]({{< relref "/develop/clients/jedis" >}}) (synchronous Java client) - [Lettuce]({{< relref "/develop/clients/lettuce" >}}) (asynchronous Java client) - [go-redis]({{< relref "/develop/clients/go" >}}) (Go client) diff --git a/content/operate/rs/references/client_references/_index.md b/content/operate/rs/references/client_references/_index.md index 1c9c43022c..dcdf81d173 100644 --- a/content/operate/rs/references/client_references/_index.md +++ b/content/operate/rs/references/client_references/_index.md @@ -18,7 +18,7 @@ To connect to Redis instances from within your application, use a Redis client l | Language | Client name | | :---------- | :------------- | -| .Net | [NRedisStack]({{< relref "/develop/clients/dotnet" >}}) | +| .Net | [StackExchange.Redis]({{< relref "/develop/clients/dotnet" >}}) | | Go | [go-redis]({{< relref "/develop/clients/go" >}}) | | Java | [Jedis]({{< relref "/develop/clients/jedis" >}}) (Synchronous) and [Lettuce]({{< relref "/develop/clients/lettuce" >}}) (Asynchronous) | | Node.js | [node-redis]({{< relref "/develop/clients/nodejs" >}}) | diff --git a/data/components/index.json b/data/components/index.json index c7087fb81c..56eec6d8dc 100644 --- a/data/components/index.json +++ b/data/components/index.json @@ -9,6 +9,8 @@ "clients": [ "nredisstack_sync", "nredisstack_async", + "seredis_sync", + "seredis_async", "go_redis", "node_redis", "ioredis", diff --git a/data/components/nredisstack_async.json b/data/components/nredisstack_async.json index 77258efaad..27d38d958f 100644 --- a/data/components/nredisstack_async.json +++ b/data/components/nredisstack_async.json @@ -3,13 +3,17 @@ "type": "client", "name": "NRedisStack_Async", "language": "C#", - "label": "C#-Async", + "label": "C#-Async (NRedisStack)", "repository": { "git_uri": "https://github.com/redis/NRedisStack" }, "examples": { "git_uri": "https://github.com/redis/NRedisStack", "path": "tests/Doc/Async", - "pattern": "*.cs" + "pattern": "*.cs", + "content_filter": { + "contains": "using NRedisStack", + "exclude_line_contains": "using NRedisStack.Tests" + } } } diff --git a/data/components/nredisstack_sync.json b/data/components/nredisstack_sync.json index c29d15da5c..4c241a46d9 100644 --- a/data/components/nredisstack_sync.json +++ b/data/components/nredisstack_sync.json @@ -3,13 +3,17 @@ "type": "client", "name": "NRedisStack_Sync", "language": "C#", - "label": "C#-Sync", + "label": "C#-Sync (NRedisStack)", "repository": { "git_uri": "https://github.com/redis/NRedisStack" }, "examples": { "git_uri": "https://github.com/redis/NRedisStack", "path": "tests/Doc", - "pattern": "*.cs" + "pattern": "*.cs", + "content_filter": { + "contains": "using NRedisStack", + "exclude_line_contains": "using NRedisStack.Tests" + } } } diff --git a/data/components/seredis_async.json b/data/components/seredis_async.json new file mode 100644 index 0000000000..b86fa70f0a --- /dev/null +++ b/data/components/seredis_async.json @@ -0,0 +1,19 @@ +{ + "id": "seredis_async", + "type": "client", + "name": "SERedis_Async", + "language": "C#", + "label": "C#-Async (SE.Redis)", + "repository": { + "git_uri": "https://github.com/redis/NRedisStack" + }, + "examples": { + "git_uri": "https://github.com/redis/NRedisStack", + "path": "tests/Doc/Async", + "pattern": "*.cs", + "content_filter": { + "not_contains": "using NRedisStack", + "exclude_line_contains": "using NRedisStack.Tests" + } + } +} diff --git a/data/components/seredis_sync.json b/data/components/seredis_sync.json new file mode 100644 index 0000000000..a5e2869e1f --- /dev/null +++ b/data/components/seredis_sync.json @@ -0,0 +1,19 @@ +{ + "id": "seredis_sync", + "type": "client", + "name": "SERedis_Sync", + "language": "C#", + "label": "C#-Sync (SE.Redis)", + "repository": { + "git_uri": "https://github.com/redis/NRedisStack" + }, + "examples": { + "git_uri": "https://github.com/redis/NRedisStack", + "path": "tests/Doc", + "pattern": "*.cs", + "content_filter": { + "not_contains": "using NRedisStack", + "exclude_line_contains": "using NRedisStack.Tests" + } + } +} diff --git a/layouts/partials/components/api-methods-tab.html b/layouts/partials/components/api-methods-tab.html index 225384e8e3..dbf54183f5 100644 --- a/layouts/partials/components/api-methods-tab.html +++ b/layouts/partials/components/api-methods-tab.html @@ -17,7 +17,11 @@ {{ $cmdOverrides := index $apiOverrides $commandName }} {{/* Define client order explicitly */}} -{{ $clientOrder := slice "Python" "Node.js" "Java-Sync" "Lettuce-Sync" "Java-Async" "Java-Reactive" "Go" "C#-Sync" "C#-Async" "PHP" "Rust-Sync" "Rust-Async" }} +{{/* $clientOrder controls the dropdown UI and signature rendering - one entry per mappingClientId */}} +{{ $clientOrder := slice "Python" "Node.js" "Java-Sync" "Lettuce-Sync" "Java-Async" "Java-Reactive" "Go" "C#-Sync (NRedisStack)" "C#-Async (NRedisStack)" "PHP" "Rust-Sync" "Rust-Async" }} +{{/* $jsClientOrder also includes SE.Redis variants so the localStorage tab-sync works when a user + has a SE.Redis tab selected on a content page and then visits a command reference page */}} +{{ $jsClientOrder := slice "Python" "Node.js" "Java-Sync" "Lettuce-Sync" "Java-Async" "Java-Reactive" "Go" "C#-Sync (NRedisStack)" "C#-Async (NRedisStack)" "C#-Sync (SE.Redis)" "C#-Async (SE.Redis)" "PHP" "Rust-Sync" "Rust-Async" }}