0
# Data Querying and Views
1
2
The KVStore provides powerful querying capabilities through the KVStoreView and KVStoreIterator interfaces. These allow for efficient data retrieval with filtering, sorting, pagination, and range queries without loading all data into memory.
3
4
## Capabilities
5
6
### KVStoreView
7
8
Configurable view for iterating over values in a KVStore with support for sorting, filtering, and pagination.
9
10
```java { .api }
11
/**
12
* A configurable view that allows iterating over values in a KVStore.
13
* Methods can be chained to configure iteration behavior.
14
*/
15
public abstract class KVStoreView<T> implements Iterable<T> {
16
17
/**
18
* Reverses the order of iteration. By default, iterates in ascending order.
19
* @return This view instance for method chaining
20
*/
21
public KVStoreView<T> reverse();
22
23
/**
24
* Iterates according to the given index.
25
* @param name The name of the index to use for iteration
26
* @return This view instance for method chaining
27
*/
28
public KVStoreView<T> index(String name);
29
30
/**
31
* Defines the value of the parent index when iterating over a child index.
32
* Required for iterating over child indices.
33
* @param value The parent index value to match
34
* @return This view instance for method chaining
35
*/
36
public KVStoreView<T> parent(Object value);
37
38
/**
39
* Iterates starting at the given value of the chosen index (inclusive).
40
* @param value The starting value for iteration
41
* @return This view instance for method chaining
42
*/
43
public KVStoreView<T> first(Object value);
44
45
/**
46
* Stops iteration at the given value of the chosen index (inclusive).
47
* @param value The ending value for iteration
48
* @return This view instance for method chaining
49
*/
50
public KVStoreView<T> last(Object value);
51
52
/**
53
* Limits iteration to a maximum number of elements.
54
* @param max Maximum number of elements to retrieve (must be positive)
55
* @return This view instance for method chaining
56
*/
57
public KVStoreView<T> max(long max);
58
59
/**
60
* Skips a number of elements at the start of iteration.
61
* Skipped elements are not counted against max().
62
* @param n Number of elements to skip
63
* @return This view instance for method chaining
64
*/
65
public KVStoreView<T> skip(long n);
66
67
/**
68
* Returns an iterator for the current configuration.
69
* @return A closeable iterator instance
70
* @throws Exception if iterator creation fails
71
*/
72
public KVStoreIterator<T> closeableIterator() throws Exception;
73
}
74
```
75
76
### KVStoreIterator
77
78
Enhanced iterator interface providing batch operations and resource management for efficient data access.
79
80
```java { .api }
81
/**
82
* An iterator for KVStore with resource management and batch operations.
83
* Should be explicitly closed after use unless all elements are consumed.
84
*/
85
public interface KVStoreIterator<T> extends Iterator<T>, Closeable {
86
87
/**
88
* Retrieve multiple elements from the store in a single operation.
89
* @param max Maximum number of elements to retrieve
90
* @return List of up to 'max' elements
91
*/
92
List<T> next(int max);
93
94
/**
95
* Skip elements in the iterator efficiently.
96
* @param n Number of elements to skip
97
* @return true if there are items left after skipping, false otherwise
98
*/
99
boolean skip(long n);
100
}
101
```
102
103
**Usage Examples:**
104
105
```java
106
import org.apache.spark.util.kvstore.*;
107
import java.util.List;
108
109
// Assume we have a Task class with indexed fields
110
public class Task {
111
@KVIndex
112
public String id;
113
114
@KVIndex("priority")
115
public int priority;
116
117
@KVIndex("status")
118
public String status;
119
120
@KVIndex("userId")
121
public String userId;
122
123
public Task(String id, int priority, String status, String userId) {
124
this.id = id;
125
this.priority = priority;
126
this.status = status;
127
this.userId = userId;
128
}
129
}
130
131
// Basic iteration over all tasks
132
KVStoreView<Task> allTasks = store.view(Task.class);
133
for (Task task : allTasks) {
134
System.out.println("Task: " + task.id);
135
}
136
137
// Query high priority tasks (priority >= 8) in descending order
138
KVStoreView<Task> highPriorityTasks = store.view(Task.class)
139
.index("priority")
140
.first(8)
141
.reverse();
142
143
for (Task task : highPriorityTasks) {
144
System.out.println("High priority task: " + task.id + " (priority: " + task.priority + ")");
145
}
146
147
// Get first 10 running tasks, skipping the first 5
148
KVStoreView<Task> runningTasks = store.view(Task.class)
149
.index("status")
150
.first("running")
151
.last("running")
152
.skip(5)
153
.max(10);
154
155
// Using closeable iterator for resource management
156
try (KVStoreIterator<Task> iterator = runningTasks.closeableIterator()) {
157
while (iterator.hasNext()) {
158
Task task = iterator.next();
159
System.out.println("Running task: " + task.id);
160
}
161
}
162
163
// Batch operations with iterator
164
try (KVStoreIterator<Task> iterator = store.view(Task.class).closeableIterator()) {
165
List<Task> batch;
166
while (!(batch = iterator.next(100)).isEmpty()) {
167
processBatch(batch);
168
}
169
}
170
171
// Range queries - tasks with priority between 5 and 9
172
KVStoreView<Task> mediumPriorityTasks = store.view(Task.class)
173
.index("priority")
174
.first(5)
175
.last(9);
176
177
// Skip and pagination
178
KVStoreView<Task> page2Tasks = store.view(Task.class)
179
.skip(20) // Skip first 20 tasks
180
.max(10); // Get next 10 tasks
181
182
// Parent-child relationships (if using parent indices)
183
// Assuming we have a parent index relationship
184
KVStoreView<Task> userTasks = store.view(Task.class)
185
.index("userId")
186
.parent("user-123");
187
```
188
189
### Query Patterns
190
191
**Simple Queries:**
192
193
```java
194
// Get all items of a type
195
KVStoreView<Task> all = store.view(Task.class);
196
197
// Get items sorted by an index
198
KVStoreView<Task> byPriority = store.view(Task.class).index("priority");
199
200
// Reverse sort order
201
KVStoreView<Task> descending = store.view(Task.class).index("priority").reverse();
202
```
203
204
**Range Queries:**
205
206
```java
207
// Items with index value >= start
208
KVStoreView<Task> fromStart = store.view(Task.class).index("priority").first(5);
209
210
// Items with index value <= end
211
KVStoreView<Task> toEnd = store.view(Task.class).index("priority").last(9);
212
213
// Items with index value between start and end (inclusive)
214
KVStoreView<Task> range = store.view(Task.class).index("priority").first(5).last(9);
215
216
// Exact match (start and end are the same)
217
KVStoreView<Task> exact = store.view(Task.class).index("status").first("running").last("running");
218
```
219
220
**Pagination:**
221
222
```java
223
// First page (items 1-20)
224
KVStoreView<Task> page1 = store.view(Task.class).max(20);
225
226
// Second page (items 21-40)
227
KVStoreView<Task> page2 = store.view(Task.class).skip(20).max(20);
228
229
// Third page (items 41-60)
230
KVStoreView<Task> page3 = store.view(Task.class).skip(40).max(20);
231
```
232
233
**Resource Management:**
234
235
```java
236
// Automatic resource cleanup with enhanced for loop
237
for (Task task : store.view(Task.class)) {
238
// Iterator is automatically closed when loop completes
239
processTask(task);
240
}
241
242
// Manual resource management for partial iteration
243
KVStoreIterator<Task> iterator = store.view(Task.class).closeableIterator();
244
try {
245
if (iterator.hasNext()) {
246
Task first = iterator.next();
247
// Process only the first task, then exit
248
return processTask(first);
249
}
250
} finally {
251
iterator.close(); // Important: close manually when not exhausting iterator
252
}
253
254
// Try-with-resources for automatic cleanup
255
try (KVStoreIterator<Task> iterator = store.view(Task.class).closeableIterator()) {
256
while (iterator.hasNext()) {
257
Task task = iterator.next();
258
if (shouldStop(task)) {
259
break; // Iterator will be closed automatically
260
}
261
processTask(task);
262
}
263
}
264
```