or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-operations.mdindex.mdindexing-system.mdquerying-views.mdstorage-backends.md

querying-views.mddocs/

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

```