Skip to content

Commit 7cf1d2f

Browse files
Merge branch 'release-k8s-asgard' into DOC-6002
2 parents ac6f3be + 4741128 commit 7cf1d2f

File tree

103 files changed

+1706
-232
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

103 files changed

+1706
-232
lines changed

build/components/example.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
PREFIXES = {
2424
'python': '#',
2525
'node.js': '//',
26+
'ioredis': '//',
2627
'java': '//',
2728
'java-sync': '//',
2829
'java-async': '//',

build/local_examples.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,20 @@ def get_client_name_from_language(language: str) -> str:
5959
def get_client_name_from_language_and_path(language: str, path: str) -> str:
6060
"""Get client name from language with path-based overrides.
6161
62+
For JavaScript (.js) files, override based on path substrings:
63+
- If 'ioredis' in path -> ioredis
64+
- Otherwise -> Node.js
65+
6266
For Java (.java) files, override based on path substrings:
6367
- If 'lettuce-sync' in path -> Lettuce-Sync
6468
- If 'lettuce-async' in path -> Java-Async
6569
- If 'lettuce-reactive' in path -> Java-Reactive
6670
6771
Substring checks are case-sensitive and can appear anywhere in the path.
6872
"""
73+
if language == 'node.js':
74+
if 'ioredis' in path:
75+
return 'ioredis'
6976
if language == 'java':
7077
if 'lettuce-sync' in path:
7178
return 'Lettuce-Sync'
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
# Implementation Notes: Table of Contents Metadata
2+
3+
## Overview
4+
5+
This document captures lessons learned from implementing auto-generated table of contents (TOC) metadata for Redis documentation pages. These insights should help guide future metadata feature implementations.
6+
7+
## Key Lessons
8+
9+
### 1. Start with Hugo's Built-in Functions
10+
11+
**Lesson**: Always check what Hugo provides before building custom solutions.
12+
13+
**Context**: Initial attempts tried to manually extract headers from page content using custom partials. This was complex, error-prone, and required parsing HTML/Markdown.
14+
15+
**Solution**: Hugo's `.TableOfContents` method already generates HTML TOC from page headings. Using this as the source was much simpler and more reliable.
16+
17+
**Takeaway**: For future metadata features, audit Hugo's built-in methods first. They often solve 80% of the problem with minimal code.
18+
19+
### 2. Regex Substitution for Format Conversion
20+
21+
**Lesson**: Simple regex transformations can convert between formats more reliably than complex parsing.
22+
23+
**Context**: Converting HTML to JSON seemed like it would require a full HTML parser or complex state machine.
24+
25+
**Solution**: Breaking the conversion into small, sequential regex steps:
26+
1. Remove wrapper elements (`<nav>`, `</nav>`)
27+
2. Replace structural tags (`<ul>``[`, `</ul>``]`)
28+
3. Replace content tags (`<li><a href="#ID">TITLE</a>``{"id":"ID","title":"TITLE"`)
29+
4. Add structural elements (commas, nested arrays)
30+
31+
**Takeaway**: For format conversions, think in terms of sequential substitution patterns rather than parsing. This is often simpler and more maintainable.
32+
33+
### 3. Hugo Template Whitespace Matters
34+
35+
**Lesson**: Hugo template whitespace and comments generate output that affects final formatting.
36+
37+
**Context**: Generated JSON had many blank lines, making it less readable.
38+
39+
**Solution**: Use Hugo's whitespace trimming markers (`{{-` and `-}}`) to prevent unwanted newlines.
40+
41+
**Takeaway**: When generating structured output (JSON, YAML), always consider whitespace. Test the final output, not just the template logic.
42+
43+
### 4. Markdown Templates Have Different Processing Rules
44+
45+
**Lesson**: Hugo's markdown template processor (`.md` files) behaves differently from HTML templates.
46+
47+
**Context**: Initial attempts to include metadata in markdown output failed because the template processor treated code blocks as boundaries.
48+
49+
**Solution**: Place metadata generation in the template itself, not in content blocks. Use `safeHTML` filter to prevent HTML entity escaping.
50+
51+
**Takeaway**: When targeting multiple output formats, test each format separately. Markdown templates have unique constraints that HTML templates don't have.
52+
53+
### 5. Validate Against Schema Early
54+
55+
**Lesson**: Create the schema before or immediately after implementation, not after.
56+
57+
**Context**: Schema was created last, after implementation was complete.
58+
59+
**Better approach**: Define the schema first, then implement to match it. This:
60+
- Clarifies the target structure
61+
- Enables validation during development
62+
- Provides documentation for implementers
63+
- Helps catch structural issues early
64+
65+
**Takeaway**: For future metadata features, write the schema first as a specification.
66+
67+
### 6. Test Multiple Page Types
68+
69+
**Lesson**: Metadata features must work across different page types with different content.
70+
71+
**Context**: Implementation was tested on data types pages and command pages, which have different metadata fields.
72+
73+
**Takeaway**: Always test on at least 2-3 different page types to ensure the feature is robust and handles optional fields correctly.
74+
75+
## Implementation Checklist for Future Metadata Features
76+
77+
When implementing new metadata features, follow this order:
78+
79+
1. **Define the schema** (`static/schemas/feature-name.json`)
80+
- Specify required and optional fields
81+
- Use JSON Schema Draft 7
82+
- Include examples
83+
84+
2. **Create documentation** (`build/metadata_docs/FEATURE_NAME_FORMAT.md`)
85+
- Explain the purpose and structure
86+
- Show examples
87+
- Document embedding locations (HTML, Markdown)
88+
89+
3. **Implement the feature**
90+
- Create/modify Hugo partials
91+
- Test on multiple page types
92+
- Verify output in both HTML and Markdown formats
93+
94+
4. **Validate the output**
95+
- Write validation scripts
96+
- Test against the schema
97+
- Check whitespace and formatting
98+
99+
5. **Document implementation notes**
100+
- Capture lessons learned
101+
- Note any workarounds or gotchas
102+
- Provide guidance for future similar features
103+
104+
## Common Gotchas
105+
106+
- **HTML entity escaping**: Use `safeHTML` filter when outputting HTML/JSON in markdown templates
107+
- **Whitespace in templates**: Use `{{-` and `-}}` to trim whitespace
108+
- **Nested structures**: Test deeply nested content to ensure regex patterns handle all cases
109+
- **Optional fields**: Remember that not all pages have all metadata fields
110+
- **Markdown vs HTML**: Always test both output formats
111+
112+
## Tools and Techniques
113+
114+
- **Hugo filters**: `replaceRE`, `jsonify`, `safeHTML`
115+
- **Validation**: Python's `jsonschema` library for schema validation
116+
- **Testing**: Extract metadata from generated files and validate against schema
117+
- **Debugging**: Use `grep` and `head` to inspect generated output
118+
119+
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
# Page Metadata Format
2+
3+
## Overview
4+
5+
Redis documentation pages include AI-friendly metadata that helps AI agents understand page structure, content, and navigation. This metadata is automatically generated during the Hugo build process and embedded in both HTML and Markdown output formats.
6+
7+
## Metadata Structure
8+
9+
### Core Fields (Required)
10+
11+
- **`title`** (string, required): The page title
12+
- **`description`** (string, required): A brief description of the page content
13+
14+
### Navigation Fields
15+
16+
- **`tableOfContents`** (object): Hierarchical structure of page sections
17+
- **`sections`** (array): Array of top-level sections
18+
- **`id`** (string): Unique identifier matching the heading anchor ID
19+
- **`title`** (string): Display title of the section
20+
- **`children`** (array, optional): Nested subsections with the same structure
21+
22+
### Categorization Fields
23+
24+
- **`categories`** (array): Category tags for the page (e.g., `["docs", "develop", "stack"]`)
25+
- **`scope`** (string): Scope or domain of the page content
26+
- **`topics`** (array): Related topics
27+
- **`relatedPages`** (array): Links to related documentation pages
28+
29+
### Command Reference Fields (for `/commands/` pages)
30+
31+
- **`arguments`** (array): Command arguments
32+
- **`syntax_fmt`** (string): Command syntax format
33+
- **`complexity`** (string): Time complexity of the command
34+
- **`group`** (string): Command group
35+
- **`command_flags`** (array): Flags associated with the command
36+
- **`acl_categories`** (array): ACL categories for the command
37+
- **`since`** (string): Redis version when the command was introduced
38+
- **`arity`** (integer): Number of arguments the command accepts
39+
- **`key_specs`** (array): Key specifications for the command
40+
41+
## Example
42+
43+
```json
44+
{
45+
"title": "Redis data types",
46+
"description": "Overview of data types supported by Redis",
47+
"categories": ["docs", "develop", "stack", "oss"],
48+
"tableOfContents": {
49+
"sections": [
50+
{
51+
"id": "data-types",
52+
"title": "Data types",
53+
"children": [
54+
{"id": "strings", "title": "Strings"},
55+
{"id": "lists", "title": "Lists"},
56+
{"id": "sets", "title": "Sets"}
57+
]
58+
},
59+
{
60+
"id": "time-series",
61+
"title": "Time series"
62+
}
63+
]
64+
}
65+
}
66+
```
67+
68+
## Embedding
69+
70+
### HTML Output
71+
72+
Metadata is embedded in a `<script>` tag in the page header:
73+
74+
```html
75+
<script type="application/json" data-ai-metadata>
76+
{...metadata...}
77+
</script>
78+
```
79+
80+
### Markdown Output (`.html.md`)
81+
82+
Metadata is embedded in a JSON code block at the top of the page:
83+
84+
````markdown
85+
```json metadata
86+
{...metadata...}
87+
```
88+
````
89+
90+
## Auto-Generation
91+
92+
The `tableOfContents` is automatically generated from page headings using Hugo's built-in `.TableOfContents` method. The HTML structure is converted to JSON using regex substitutions in the `layouts/partials/toc-json-regex.html` partial.
93+
94+
## Schema
95+
96+
The complete JSON schema is available at: `https://redis.io/schemas/page-metadata.json`
97+
98+
This schema enables:
99+
- Validation of metadata structure
100+
- IDE autocomplete and type checking
101+
- AI agent understanding of page structure
102+
- Consistent metadata across all pages
103+
104+
## Notes
105+
106+
- The in-page JSON metadata does **not** include a `$schema` reference. The schema is available separately for validation and documentation purposes.
107+
- The metadata is auto-generated during the Hugo build process and does not require manual maintenance.
108+

config.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ tagManagerId = "GTM-TKZ6J9R"
4646
gitHubRepo = "https://github.com/redis/docs"
4747

4848
# Display and sort order for client examples
49-
clientsExamples = ["Python", "Node.js", "Java-Sync", "Lettuce-Sync", "Java-Async", "Java-Reactive", "Go", "C", "C#-Sync", "C#-Async", "RedisVL", "PHP", "Rust-Sync", "Rust-Async"]
49+
clientsExamples = ["Python", "Node.js", "ioredis", "Java-Sync", "Lettuce-Sync", "Java-Async", "Java-Reactive", "Go", "C", "C#-Sync", "C#-Async", "RedisVL", "PHP", "Rust-Sync", "Rust-Async"]
5050
searchService = "/convai/api/search-service"
5151
ratingsService = "/docusight/api/rate/docs"
5252

@@ -61,6 +61,7 @@ rdi_current_version = "1.15.1"
6161
[params.clientsConfig]
6262
"Python"={quickstartSlug="redis-py"}
6363
"Node.js"={quickstartSlug="nodejs"}
64+
"ioredis"={quickstartSlug="ioredis"}
6465
"Java-Sync"={quickstartSlug="jedis"}
6566
"Lettuce-Sync"={quickstartSlug="lettuce"}
6667
"Java-Async"={quickstartSlug="lettuce"}

content/commands/bf.info.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,13 +117,14 @@ redis> BF.INFO bf1 CAPACITY
117117
tab2="RESP3" >}}
118118

119119
One of the following:
120-
* [Array reply]({{< relref "/develop/reference/protocol-spec#arrays" >}}) with argument name ([Simple string reply]({{< relref "/develop/reference/protocol-spec#simple-strings" >}})) and value ([Integer reply]({{< relref "/develop/reference/protocol-spec#integers" >}})) pairs.
120+
* A singleton [array reply]({{< relref "/develop/reference/protocol-spec#arrays" >}}) with an [integer]({{< relref "/develop/reference/protocol-spec#integers" >}}) representing the value of the requested property.
121+
* An [array reply]({{< relref "/develop/reference/protocol-spec#arrays" >}}) with [simple string]({{< relref "/develop/reference/protocol-spec#simple-strings" >}}) and [integer]({{< relref "/develop/reference/protocol-spec#integers" >}}) pairs.
121122
* [Simple error reply]({{< relref "/develop/reference/protocol-spec#simple-errors" >}}) in these cases: invalid arguments, wrong key type, or when the key does not exist.
122123

123124
-tab-sep-
124125

125126
One of the following:
126-
* [Map reply]({{< relref "/develop/reference/protocol-spec#maps" >}}) with argument name ([Simple string reply]({{< relref "/develop/reference/protocol-spec#simple-strings" >}})) and value ([Integer reply]({{< relref "/develop/reference/protocol-spec#integers" >}})) pairs.
127+
* [Map reply]({{< relref "/develop/reference/protocol-spec#maps" >}}) with [simple string]({{< relref "/develop/reference/protocol-spec#simple-strings" >}}) and [integer]({{< relref "/develop/reference/protocol-spec#integers" >}}) pairs.
127128
* [Simple error reply]({{< relref "/develop/reference/protocol-spec#simple-errors" >}}) in these cases: invalid arguments, wrong key type, or when the key does not exist.
128129

129130
{{< /multitabs >}}

content/commands/cluster-slot-stats.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,14 @@ The command reports on the following statistics:
105105

106106
* `KEY-COUNT`: Number of keys stored in the slot.
107107
* `CPU-USEC`: CPU time (in microseconds) spent handling the slot.
108+
* `MEMORY-BYTES`: Number of bytes allocated by the slot.
108109
* `NETWORK-BYTES-IN`: Total inbound network traffic (in bytes) received by the slot.
109110
* `NETWORK-BYTES-OUT`: Total outbound network traffic (in bytes) sent from the slot.
110111

112+
{{< note>}}
113+
`MEMORY-BYTES` requires that you set `cluster-slot-stats-enabled` to `yes` in your `redis.conf` file.
114+
{{< /note >}}
115+
111116
## Redis Enterprise and Redis Cloud compatibility
112117

113118
| Redis<br />Enterprise | Redis<br />Cloud | <span style="min-width: 9em; display: table-cell">Notes</span> |

content/commands/config-set.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,11 @@ It is possible to switch persistence from RDB snapshotting to append-only file
7272
(and the other way around) using the `CONFIG SET` command.
7373
See the [persistence page]({{< relref "/operate/oss_and_stack/management/persistence" >}}) for more information.
7474

75-
In general what you should know is that setting the `appendonly` parameter to
76-
`yes` will start a background process to save the initial append-only file
75+
```
76+
CONFIG SET appendonly yes
77+
```
78+
79+
Setting the `appendonly` parameter as shown above will start a background process to save the initial append-only file
7780
(obtained from the in memory data set), and will append all the subsequent
7881
commands on the append-only file, thus obtaining exactly the same effect of a
7982
Redis server that started with AOF turned on since the start.

content/commands/ft.hybrid.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -515,7 +515,6 @@ syntax_fmt: "FT.HYBRID index\n SEARCH query\n [SCORER scorer]\n [YIELD_SC
515515
\ [arg ...] [AS name] ...]] ...]]\n [APPLY expression AS name [APPLY expression\
516516
\ AS name ...]]\n [FILTER filter]\n PARAMS nargs vector_param vector_blob [name\
517517
\ value ...]\n [TIMEOUT timeout]"
518-
syntax_fmt: FT.HYBRID
519518
title: FT.HYBRID
520519
---
521520

content/develop/ai/search-and-query/advanced-concepts/dialects.md

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ The Dialect version 2 enhancements also introduce simplified syntax for logical
131131

132132
## `DIALECT 3` (Deprecated)
133133

134-
Dialect version 3 was introduced in the [2.6](https://github.com/RediSearch/RediSearch/releases/tag/v2.6.3) release. This version introduced support for multi-value indexing and querying of attributes for any attribute type ( [TEXT]({{< relref "develop/ai/search-and-query/indexing/#index-json-arrays-as-text" >}}), [TAG]({{< relref "develop/ai/search-and-query/indexing/#index-json-arrays-as-tag" >}}), [NUMERIC]({{< relref "develop/ai/search-and-query/indexing/#index-json-arrays-as-numeric" >}}), [GEO]({{< relref "develop/ai/search-and-query/indexing/#index-json-arrays-as-geo" >}}) and [VECTOR]({{< relref "develop/ai/search-and-query/indexing/#index-json-arrays-as-vector" >}})) defined by a [JSONPath]({{< relref "/develop/data-types/json/path" >}}) leading to an array or multiple scalar values. Support for [GEOSHAPE]({{< relref "/develop/ai/search-and-query/query/geo-spatial" >}}) queries was also introduced in this dialect.
134+
Dialect version 3 was introduced in the [2.6](https://github.com/RediSearch/RediSearch/releases/tag/v2.6.3) release. This version introduced support for multi-value indexing and querying of attributes for any attribute type ( [TEXT]({{< relref "develop/ai/search-and-query/indexing/#index-json-arrays-as-text" >}}), [TAG]({{< relref "develop/ai/search-and-query/indexing/#index-json-arrays-as-tag" >}}), [NUMERIC]({{< relref "develop/ai/search-and-query/indexing/#index-json-arrays-as-numeric" >}}), [GEO]({{< relref "develop/ai/search-and-query/indexing/#index-json-arrays-as-geo" >}}) and [VECTOR]({{< relref "develop/ai/search-and-query/indexing/#index-json-arrays-as-vector" >}})) defined by a [JSONPath]({{< relref "/develop/data-types/json/path" >}}) leading to an array or multiple scalar values. Support for [GEOSHAPE]({{< relref "/develop/ai/search-and-query/query/geo-spatial" >}}) queries was also introduced in this version.
135135

136136
The primary difference between dialects version 2 and version 3 is that JSON is returned rather than scalars for multi-value attributes. Apart from specifying `DIALECT 3` at the end of a [`FT.SEARCH`]({{< relref "commands/ft.search/" >}}) command, there are no other syntactic changes. Dialect version 1 remains the default dialect. To use dialect version 3, append `DIALECT 3` to your query command.
137137

@@ -191,10 +191,6 @@ Now search, with and without `DIALECT 3`.
191191
192192
Both elements are returned.
193193
194-
{{% alert title=Note %}}
195-
DIALECT 3 is required for shape-based (`POINT` or `POLYGON`) geospatial queries.
196-
{{% /alert %}}
197-
198194
## `DIALECT 4` (Deprecated)
199195
200196
Dialect version 4 was introduced in the [2.8](https://github.com/RediSearch/RediSearch/releases/tag/v2.8.4) release. It introduces performance optimizations for sorting operations on [`FT.SEARCH`]({{< relref "commands/ft.search/" >}}) and [`FT.AGGREGATE`]({{< relref "commands/ft.aggregate/" >}}). Apart from specifying `DIALECT 4` at the end of a [`FT.SEARCH`]({{< relref "commands/ft.search/" >}}) command, there are no other syntactic changes. Dialect version 1 remains the default dialect. To use dialect version 4, append `DIALECT 4` to your query command.
@@ -279,4 +275,4 @@ You can also change the query dialect on an already running server using the `FT
279275

280276
```
281277
FT.CONFIG SET DEFAULT_DIALECT 2
282-
```
278+
```

0 commit comments

Comments
 (0)