Skip to content

Commit 6896339

Browse files
committed
docs: add comprehensive HybridQuery documentation
Adds complete documentation for HybridQuery class which was previously undocumented. The documentation includes: README.md: - Added HybridQuery to the list of query types - Included example showing text+vector hybrid search with alpha weighting - Demonstrates how hybrid scoring works hybrid-queries.adoc: - New "Hybrid Search: Text + Vector" section at the top - Explains difference between hybrid search and filtered vector search - Basic HybridQuery usage examples - Alpha parameter tuning guide (text vs vector balance) - Filter integration with both Filter objects and string expressions - Documents new string filter expression feature - Custom stopwords configuration - Complete working example with schema and query Key features documented: - Text + vector weighted scoring with alpha parameter - Filter objects (existing feature) - String filter expressions (new in v0.0.2) - Stopwords customization - Return fields and result formatting
1 parent 44b0c8a commit 6896339

File tree

2 files changed

+223
-2
lines changed

2 files changed

+223
-2
lines changed

README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,27 @@ Define queries and perform advanced searches over your indices, including the co
196196
List<Map<String, Object>> results = index.query(filteredQuery);
197197
```
198198
199+
- **HybridQuery** - Combines text and vector search with weighted scoring:
200+
201+
```java
202+
import com.redis.vl.query.HybridQuery;
203+
import com.redis.vl.query.Filter;
204+
205+
// Hybrid search: text + vector with alpha weighting
206+
HybridQuery hybridQuery = HybridQuery.builder()
207+
.text("machine learning algorithms")
208+
.textFieldName("description")
209+
.vector(queryVector)
210+
.vectorFieldName("embedding")
211+
.filterExpression(Filter.tag("category", "AI"))
212+
.alpha(0.7f) // 70% vector, 30% text
213+
.numResults(10)
214+
.build();
215+
216+
List<Map<String, Object>> results = index.query(hybridQuery);
217+
// Results scored by: alpha * vector_similarity + (1-alpha) * text_score
218+
```
219+
199220
- **VectorRangeQuery** - Vector search within a defined range paired with customizable filters
200221
- **FilterQuery** - Standard search using filters and the full-text search
201222
- **CountQuery** - Count the number of indexed records given attributes

docs/content/modules/ROOT/pages/hybrid-queries.adoc

Lines changed: 202 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,209 @@
33

44
In this guide, we will explore more complex queries that can be performed with RedisVL.
55

6-
== Hybrid Queries
6+
== Hybrid Search: Text + Vector
77

8-
Hybrid queries are queries that combine multiple types of filters. For example, you may want to search for a user that is a certain age, has a certain job, and is within a certain distance of a location. This is a hybrid query that combines numeric, tag, and geographic filters.
8+
RedisVL supports true hybrid search that combines both text and vector similarity in a single query using the `HybridQuery` class. This is different from filtered vector search - it actually scores documents based on a weighted combination of both text relevance and vector similarity.
9+
10+
=== Basic HybridQuery
11+
12+
A `HybridQuery` combines full-text search with vector similarity search:
13+
14+
[source,java]
15+
----
16+
import com.redis.vl.query.HybridQuery;
17+
18+
// Create a hybrid query combining text and vector search
19+
HybridQuery query = HybridQuery.builder()
20+
.text("medical professional with expertise")
21+
.textFieldName("description")
22+
.vector(queryVector)
23+
.vectorFieldName("embedding")
24+
.numResults(10)
25+
.build();
26+
27+
List<Map<String, Object>> results = index.query(query);
28+
----
29+
30+
The results are scored using:
31+
```
32+
hybrid_score = (alpha) * vector_similarity + (1-alpha) * text_score
33+
```
34+
35+
Where `alpha` (default 0.7) controls the balance between vector and text similarity.
36+
37+
=== Adjusting the Alpha Parameter
38+
39+
Control the balance between text and vector similarity:
40+
41+
[source,java]
42+
----
43+
// Favor vector similarity (alpha = 0.9)
44+
HybridQuery vectorFocused = HybridQuery.builder()
45+
.text("search terms")
46+
.textFieldName("description")
47+
.vector(queryVector)
48+
.vectorFieldName("embedding")
49+
.alpha(0.9f) // 90% vector, 10% text
50+
.build();
51+
52+
// Balanced approach (alpha = 0.5)
53+
HybridQuery balanced = HybridQuery.builder()
54+
.text("search terms")
55+
.textFieldName("description")
56+
.vector(queryVector)
57+
.vectorFieldName("embedding")
58+
.alpha(0.5f) // 50% vector, 50% text
59+
.build();
60+
61+
// Favor text relevance (alpha = 0.3)
62+
HybridQuery textFocused = HybridQuery.builder()
63+
.text("search terms")
64+
.textFieldName("description")
65+
.vector(queryVector)
66+
.vectorFieldName("embedding")
67+
.alpha(0.3f) // 30% vector, 70% text
68+
.build();
69+
----
70+
71+
=== Adding Filters to HybridQuery
72+
73+
Filter hybrid search results using either Filter objects or raw Redis query strings:
74+
75+
==== Using Filter Objects
76+
77+
[source,java]
78+
----
79+
import com.redis.vl.query.Filter;
80+
81+
// Create filters
82+
Filter filter = Filter.and(
83+
Filter.tag("category", "technology"),
84+
Filter.numeric("rating").gte(4.0)
85+
);
86+
87+
// Apply to hybrid query
88+
HybridQuery query = HybridQuery.builder()
89+
.text("artificial intelligence")
90+
.textFieldName("description")
91+
.vector(queryVector)
92+
.vectorFieldName("embedding")
93+
.filterExpression(filter)
94+
.build();
95+
----
96+
97+
==== Using String Filter Expressions (New in v0.0.2)
98+
99+
For advanced use cases, you can pass raw Redis filter query strings:
100+
101+
[source,java]
102+
----
103+
// Use raw Redis query syntax
104+
String customFilter = "@category:{tech|science|engineering} @rating:[4.0 +inf]";
105+
106+
HybridQuery query = HybridQuery.builder()
107+
.text("machine learning")
108+
.textFieldName("description")
109+
.vector(queryVector)
110+
.vectorFieldName("embedding")
111+
.filterExpression(customFilter) // String filter!
112+
.build();
113+
----
114+
115+
This is useful when:
116+
117+
* You need Redis query syntax not yet supported by Filter objects
118+
* You're migrating from raw Redis queries
119+
* You want direct control over the query syntax
120+
121+
=== Custom Stopwords
122+
123+
Control which words are filtered from the text query:
124+
125+
[source,java]
126+
----
127+
import java.util.Set;
128+
129+
// Use custom stopwords
130+
Set<String> customStopwords = Set.of("the", "a", "an", "to");
131+
132+
HybridQuery query = HybridQuery.builder()
133+
.text("the quick brown fox")
134+
.textFieldName("description")
135+
.vector(queryVector)
136+
.vectorFieldName("embedding")
137+
.stopwords(customStopwords)
138+
.build();
139+
----
140+
141+
=== Complete HybridQuery Example
142+
143+
[source,java]
144+
----
145+
import com.redis.vl.index.SearchIndex;
146+
import com.redis.vl.schema.IndexSchema;
147+
import com.redis.vl.query.HybridQuery;
148+
import com.redis.vl.query.Filter;
149+
150+
// Define schema with text and vector fields
151+
String schemaYaml = """
152+
version: '0.1.0'
153+
index:
154+
name: articles-index
155+
prefix: article
156+
storage_type: hash
157+
fields:
158+
- name: title
159+
type: text
160+
- name: content
161+
type: text
162+
- name: category
163+
type: tag
164+
- name: rating
165+
type: numeric
166+
- name: embedding
167+
type: vector
168+
attrs:
169+
dims: 384
170+
distance_metric: cosine
171+
algorithm: flat
172+
datatype: float32
173+
""";
174+
175+
IndexSchema schema = IndexSchema.fromYaml(schemaYaml);
176+
SearchIndex index = new SearchIndex(schema, jedis);
177+
index.create(true);
178+
179+
// Perform hybrid search with filter
180+
Filter filter = Filter.and(
181+
Filter.tag("category", "technology"),
182+
Filter.numeric("rating").gte(4.0)
183+
);
184+
185+
HybridQuery query = HybridQuery.builder()
186+
.text("machine learning artificial intelligence")
187+
.textFieldName("content")
188+
.vector(queryVector) // Your embedding vector
189+
.vectorFieldName("embedding")
190+
.filterExpression(filter)
191+
.alpha(0.7f) // 70% vector, 30% text
192+
.numResults(10)
193+
.returnFields(List.of("title", "category", "rating"))
194+
.build();
195+
196+
List<Map<String, Object>> results = index.query(query);
197+
198+
// Results are sorted by hybrid_score (descending)
199+
for (Map<String, Object> result : results) {
200+
System.out.println("Title: " + result.get("title"));
201+
System.out.println("Score: " + result.get("hybrid_score"));
202+
System.out.println("---");
203+
}
204+
----
205+
206+
== Filtered Vector Search
207+
208+
Filtered vector search is different from hybrid search - it applies filters before or after vector search, but doesn't combine text and vector scoring. For filtered vector queries, see <<Pre-Filtering vs Post-Filtering>>.
9209

10210
== Filter Types
11211

0 commit comments

Comments
 (0)