Skip to content

Commit 52a0a20

Browse files
dwdoughertykaitlynmichael
authored andcommitted
DEV: update RQE tags doc (#1862)
* DEV: update RQE tags doc * Apply suggestions from peer review
1 parent d55e5e3 commit 52a0a20

File tree

1 file changed

+206
-81
lines changed
  • content/develop/ai/search-and-query/advanced-concepts

1 file changed

+206
-81
lines changed
Lines changed: 206 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
---
22
aliases:
33
- /develop/interact/search-and-query/advanced-concepts/tags
4+
- /develop/ai/search-and-query/advanced-concepts/tags
45
categories:
56
- docs
67
- develop
@@ -11,52 +12,78 @@ categories:
1112
- oss
1213
- kubernetes
1314
- clients
14-
description: Details about tag fields
15-
linkTitle: Tags
16-
title: Tags
15+
description: How to use tag fields for exact match searches and high-performance filtering
16+
linkTitle: Tag fields
17+
title: Tag fields
1718
weight: 6
1819
---
1920

20-
Tag fields are similar to full-text fields but they interpret the text as a simple
21-
list of *tags* delimited by a
22-
[separator](#creating-a-tag-field) character (which is a comma "," by default).
23-
This limitation means that tag fields can use simpler
24-
[tokenization]({{< relref "/develop/ai/search-and-query/advanced-concepts/escaping" >}})
25-
and encoding in the index, which is more efficient than full-text indexing.
21+
Tag fields provide exact match search capabilities with high performance and memory efficiency. Use tag fields when you need to filter documents by specific values without the complexity of full-text search tokenization.
2622

27-
The values in tag fields cannot be accessed by general field-less search and can be used only with a special syntax.
23+
Tag fields interpret text as a simple list of *tags* delimited by a [separator](#separator-options) character (comma "`,`" by default). This approach enables simpler [tokenization]({{< relref "/develop/ai/search-and-query/advanced-concepts/escaping/#tokenization-rules-for-tag-fields" >}}) and encoding, making tag indexes much more efficient than full-text indexes. Note: even though tag and text fields both use text, they are two separate field types and so you don't query them the same way.
2824

29-
The main differences between tag and full-text fields are:
25+
## Tag fields vs text fields
3026

31-
1. [Tokenization]({{< relref "/develop/ai/search-and-query/advanced-concepts/escaping#tokenization-rules-for-tag-fields" >}})
32-
is very simple for tags.
27+
Tag fields excel in scenarios requiring exact matching rather than full-text search. Choose tag fields when you need to index categorical data such as:
3328

34-
1. Stemming is not performed on tag indexes.
29+
- **Product categories**: Electronics, Clothing, Books
30+
- **User roles**: Admin, Editor, Viewer
31+
- **Status values**: Active, Pending, Completed
32+
- **Geographic regions**: US, EU, APAC
33+
- **Content types**: Video, Image, Document
3534

36-
1. Tags cannot be found from a general full-text search. If a document has a field called "tags"
37-
with the values "foo" and "bar", searching for foo or bar without a special tag modifier (see below) will not return this document.
35+
### Key differences
3836

39-
1. The index is much simpler and more compressed: frequencies or offset vectors of field flags
40-
are not stored. The index contains only document IDs encoded as deltas. This means that an entry in
41-
a tag index is usually one or two bytes long. This makes them very memory-efficient and fast.
37+
| Feature | Tag fields | Text fields |
38+
|---------|------------|-------------|
39+
| **Search type** | Exact match | Full-text search |
40+
| **Tokenization** | Simple delimiter splitting | Complex word tokenization |
41+
| **Stemming** | None | Language-specific stemming |
42+
| **Memory usage** | Very low (1-2 bytes per entry) | Higher (frequencies, positions) |
43+
| **Performance** | Fastest | Slower for exact matches |
44+
| **Multiple values** | Support comma-separated lists | Single text content |
45+
| **Case control** | Optional case-sensitive matching | Typically case-insensitive |
46+
| **Use case** | Categories, filters, IDs | Content search, descriptions |
4247

43-
1. You can create up to 1024 tag fields per index.
48+
## Technical details
4449

45-
## Creating a tag field
50+
### Index structure
51+
- **Compressed storage**: Only document IDs encoded as deltas (1-2 bytes per entry)
52+
- **No frequencies**: Unlike TEXT fields, tag indexes don't store term frequencies
53+
- **No positions**: No offset vectors or field flags stored
54+
- **Limit**: You can create up to 1024 tag fields per index
4655

47-
Tag fields can be added to the schema with the following syntax:
56+
### Tokenization differences
57+
- **Simple splitting**: Text is split only at separator characters
58+
- **No stemming**: Words are indexed exactly as written
59+
- **Case handling**: Optional case-sensitive or case-insensitive matching
60+
- **No stop words**: All tag values are indexed regardless of content
61+
62+
## Create a tag field
63+
64+
Add tag fields to your schema using this syntax:
4865

4966
```
5067
FT.CREATE ... SCHEMA ... {field_name} TAG [SEPARATOR {sep}] [CASESENSITIVE]
5168
```
5269

53-
For hashes, SEPARATOR can be any printable ASCII character; the default is a comma (`,`). For JSON, there is no default separator; you must declare one explicitly if needed.
70+
### Separator options
5471

55-
For example:
72+
- **Hash documents**: Default separator is comma (`,`). You can use any printable ASCII character
73+
- **JSON documents**: No default separator - you must specify one explicitly if needed
74+
- **Custom separators**: Use semicolon (`;`), pipe (`|`), or other characters as needed
5675

57-
```
58-
JSON.SET key:1 $ '{"colors": "red, orange, yellow"}'
59-
FT.CREATE idx on JSON PREFIX 1 key: SCHEMA $.colors AS colors TAG SEPARATOR ","
76+
### Case sensitivity
77+
78+
- **Default**: Case-insensitive matching (`red` matches `Red`, `RED`)
79+
- **CASESENSITIVE**: Preserves original case for exact matching
80+
81+
### Examples
82+
83+
**Basic tag field with JSON:**
84+
```sql
85+
JSON.SET key:1 $ '{"colors": "red, orange, yellow"}'
86+
FT.CREATE idx ON JSON PREFIX 1 key: SCHEMA $.colors AS colors TAG SEPARATOR ","
6087

6188
> FT.SEARCH idx '@colors:{orange}'
6289
1) "1"
@@ -65,105 +92,203 @@ FT.CREATE idx on JSON PREFIX 1 key: SCHEMA $.colors AS colors TAG SEPARATOR ","
6592
2) "{\"colors\":\"red, orange, yellow\"}"
6693
```
6794

68-
CASESENSITIVE can be specified to keep the original case.
95+
**Case-sensitive tags with Hash:**
96+
```sql
97+
HSET product:1 categories "Electronics,Gaming,PC"
98+
FT.CREATE products ON HASH PREFIX 1 product: SCHEMA categories TAG CASESENSITIVE
6999

70-
## Querying tag fields
100+
> FT.SEARCH products '@categories:{PC}'
101+
1) "1"
102+
2) "product:1"
103+
```
71104

72-
As mentioned above, just searching for a tag without any modifiers will not retrieve documents
73-
containing it.
105+
**Custom separator:**
106+
```sql
107+
HSET book:1 genres "Fiction;Mystery;Thriller"
108+
FT.CREATE books ON HASH PREFIX 1 book: SCHEMA genres TAG SEPARATOR ";"
109+
```
74110

75-
The syntax for matching tags in a query is as follows (the curly braces are part of the syntax):
111+
## Query tag fields
76112

77-
```
78-
@<field_name>:{ <tag> | <tag> | ...}
79-
```
113+
**Important**: Tag fields require special query syntax - you cannot find tag values with general field-less searches.
80114

81-
For example, this query finds documents with either the tag `hello world` or `foo bar`:
115+
### Basic tag query syntax
116+
117+
Use curly braces to specify tag values (the braces are part of the syntax):
82118

83119
```
84-
FT.SEARCH idx "@tags:{ hello world | foo bar }"
120+
@<field_name>:{ <tag> | <tag> | ...}
85121
```
86122

87-
Tag clauses can be combined into any sub-clause, used as negative expressions, optional expressions, etc. For example, given the following index:
123+
### Single tag match
88124

125+
Find documents with a specific tag:
126+
127+
```sql
128+
FT.SEARCH idx "@category:{Electronics}"
129+
FT.SEARCH idx "@status:{Active}"
89130
```
90-
FT.CREATE idx ON HASH PREFIX 1 test: SCHEMA title TEXT price NUMERIC tags TAG SEPARATOR ";"
91-
```
92131

93-
You can combine a full-text search on the title field, a numerical range on price, and match either the `foo bar` or `hello world` tag like this:
132+
### Multiple tag match (OR)
133+
134+
Find documents with any of the specified tags:
94135

136+
```sql
137+
FT.SEARCH idx "@tags:{ hello world | foo bar }"
138+
FT.SEARCH idx "@category:{ Electronics | Gaming | Software }"
95139
```
96-
FT.SEARCH idx "@title:hello @price:[0 100] @tags:{ foo bar | hello world }
140+
141+
### Combining with other queries
142+
143+
Tag queries work seamlessly with other field types:
144+
145+
```sql
146+
FT.CREATE idx ON HASH PREFIX 1 product: SCHEMA
147+
title TEXT
148+
price NUMERIC
149+
category TAG SEPARATOR ";"
150+
151+
# Combine text search, numeric range, and tag filter
152+
FT.SEARCH idx "@title:laptop @price:[500 1500] @category:{ Electronics | Gaming }"
97153
```
98154

99-
Tags support prefix matching with the regular `*` character:
155+
### Prefix matching
156+
157+
Use the `*` wildcard for prefix matching:
100158

159+
```sql
160+
FT.SEARCH idx "@tags:{ tech* }" # Matches: technology, technical, tech
161+
FT.SEARCH idx "@tags:{ hello\\ w* }" # Matches: "hello world", "hello web"
101162
```
102-
FT.SEARCH idx "@tags:{ hell* }"
103-
FT.SEARCH idx "@tags:{ hello\\ w* }"
104163

164+
### Negative matching
165+
166+
Exclude documents with specific tags:
167+
168+
```sql
169+
FT.SEARCH idx "-@category:{Discontinued}"
170+
FT.SEARCH idx "@title:phone -@category:{Refurbished}"
105171
```
106172

107-
## Multiple tags in a single filter
173+
## Advanced tag queries
108174

109-
Notice that including multiple tags in the same clause creates a union of all documents that contain any of the included tags. To create an intersection of documents containing all of the given tags, you should repeat the tag filter several times.
175+
### OR vs AND logic
110176

111-
For example, imagine an index of travelers, with a tag field for the cities each traveler has visited:
177+
**Single clause (OR logic)**: Find documents with ANY of the specified tags
178+
```sql
179+
@cities:{ New York | Los Angeles | Barcelona }
180+
# Returns: Documents with New York OR Los Angeles OR Barcelona
181+
```
112182

183+
**Multiple clauses (AND logic)**: Find documents with ALL of the specified tags
184+
```sql
185+
@cities:{ New York } @cities:{ Los Angeles } @cities:{ Barcelona }
186+
# Returns: Documents with New York AND Los Angeles AND Barcelona
113187
```
114-
FT.CREATE myIndex ON HASH PREFIX 1 traveler: SCHEMA name TEXT cities TAG
188+
189+
### Practical example
190+
191+
Consider a travel database:
192+
193+
```sql
194+
FT.CREATE travelers ON HASH PREFIX 1 traveler: SCHEMA
195+
name TEXT
196+
cities TAG
115197

116198
HSET traveler:1 name "John Doe" cities "New York, Barcelona, San Francisco"
199+
HSET traveler:2 name "Jane Smith" cities "New York, Los Angeles, Tokyo"
117200
```
118201

119-
For this index, the following query will return all the people who visited at least one of the following cities:
120-
202+
**Find travelers who visited any of these cities:**
203+
```sql
204+
FT.SEARCH travelers "@cities:{ New York | Los Angeles | Barcelona }"
205+
# Returns: Both John and Jane
121206
```
122-
FT.SEARCH myIndex "@cities:{ New York | Los Angeles | Barcelona }"
207+
208+
**Find travelers who visited all of these cities:**
209+
```sql
210+
FT.SEARCH travelers "@cities:{ New York } @cities:{ Barcelona }"
211+
# Returns: Only John (has both New York and Barcelona)
123212
```
124213

125-
But the next query will return all people who have visited all three cities:
214+
## Handle special characters
126215

127-
```
128-
FT.SEARCH myIndex "@cities:{ New York } @cities:{Los Angeles} @cities:{ Barcelona }"
129-
```
216+
Tag fields can contain any punctuation except the field separator, but you need to escape certain characters in queries.
130217

131-
## Including punctuation and spaces in tags
218+
### Defining tags with special characters
132219

133-
A tag field can contain any punctuation characters except for the field separator.
134-
You can use punctuation without escaping when you *define* a tag field,
135-
but you typically need to escape certain characters when you *query* the field
136-
because the query syntax itself uses the same characters.
137-
(See [Query syntax]({{< relref "/develop/ai/search-and-query/advanced-concepts/query_syntax#tag-filters" >}})
138-
for the full set of characters that require escaping.)
220+
You can store tags with punctuation without escaping:
139221

140-
For example, given the following index:
222+
```sql
223+
FT.CREATE products ON HASH PREFIX 1 test: SCHEMA tags TAG
141224

225+
HSET test:1 tags "Andrew's Top 5,Justin's Top 5,5-Star Rating"
226+
HSET test:2 tags "Best Buy,Top-Rated,Editor's Choice"
142227
```
143-
FT.CREATE punctuation ON HASH PREFIX 1 test: SCHEMA tags TAG
228+
229+
### Querying tags with special characters
230+
231+
**Escape punctuation in queries** using backslash (`\`):
232+
233+
```sql
234+
# Query for "Andrew's Top 5"
235+
FT.SEARCH products "@tags:{ Andrew\\'s Top 5 }"
236+
237+
# Query for "5-Star Rating"
238+
FT.SEARCH products "@tags:{ 5\\-Star Rating }"
239+
240+
# Query for "Editor's Choice"
241+
FT.SEARCH products "@tags:{ Editor\\'s Choice }"
144242
```
145243

146-
You can add tags that contain punctuation like this:
244+
### Characters that need escaping
245+
246+
In tag queries, escape these characters:
247+
- Single quotes: `'``\\'`
248+
- Hyphens: `-``\\-`
249+
- Parentheses: `()``\\(\\)`
250+
- Brackets: `[]{}``\\[\\]\\{\\}`
251+
- Pipes: `|``\\|`
252+
253+
### Spaces in tags
147254

255+
**Modern Redis** (v2.4+): Spaces don't need escaping in tag queries
256+
```sql
257+
FT.SEARCH products "@tags:{ Top Rated Product }"
148258
```
149-
HSET test:1 tags "Andrew's Top 5,Justin's Top 5"
259+
260+
**Older versions** or **dialect 1**: Escape spaces
261+
```sql
262+
FT.SEARCH products "@tags:{ Top\\ Rated\\ Product }"
150263
```
151264

152-
However, when you query for those tags, you must escape the punctuation characters
153-
with a backslash (`\`). So, querying for the tag `Andrew's Top 5` in
154-
[`redis-cli`]({{< relref "/develop/tools/cli" >}}) looks like this:
265+
### Best practices
155266

156-
```
157-
FT.SEARCH punctuation "@tags:{ Andrew\\'s Top 5 }"
267+
- **Use simple separators**: Stick to comma (`,`) or semicolon (`;`)
268+
- **Avoid complex punctuation**: Keep tag values simple when possible
269+
- **Test your queries**: Verify escaping works with your specific characters
270+
- **Use consistent casing**: Decide on case sensitivity early in your design
271+
272+
See [Query syntax]({{< relref "/develop/ai/search-and-query/advanced-concepts/query_syntax#tag-filters" >}}) for complete escaping rules.
273+
274+
## An e-commerce use case
275+
276+
```sql
277+
# Product categories and attributes
278+
FT.CREATE products ON HASH PREFIX 1 product: SCHEMA
279+
name TEXT
280+
category TAG
281+
brand TAG
282+
features TAG SEPARATOR ";"
283+
284+
HSET product:1 name "Gaming Laptop" category "Electronics" brand "ASUS" features "RGB;16GB RAM;SSD"
285+
286+
# Find gaming products with specific features
287+
FT.SEARCH products "@category:{Electronics} @features:{RGB} @features:{SSD}"
158288
```
159289

160-
(Note that you need the double backslash here because the terminal app itself
161-
uses the backslash as an escape character.
162-
Programming languages commonly use this convention also.)
290+
## Next steps
163291

164-
You can include spaces in a tag filter without escaping *unless* you are
165-
using a version of RediSearch earlier than v2.4 or you are using
166-
[query dialect 1]({{< relref "/develop/ai/search-and-query/advanced-concepts/dialects#dialect-1" >}}).
167-
See
168-
[Query syntax]({{< relref "/develop/ai/search-and-query/advanced-concepts/query_syntax#tag-filters" >}})
169-
for a full explanation.
292+
- Learn about [tokenization rules]({{< relref "/develop/ai/search-and-query/advanced-concepts/escaping#tokenization-rules-for-tag-fields" >}}) for tag fields
293+
- Explore [field and type options]({{< relref "/develop/ai/search-and-query/indexing/field-and-type-options" >}}) for other field types
294+
- See [query syntax]({{< relref "/develop/ai/search-and-query/advanced-concepts/query_syntax" >}}) for advanced query patterns

0 commit comments

Comments
 (0)