or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

configuration.mdimport-autotag.mdindex.mdlibrary-management.mdplugin-system.mdquery-system.mduser-interface.mdutilities-templates.md

query-system.mddocs/

0

# Query System

1

2

Sophisticated query language and parsing system for filtering library content with support for field matching, regular expressions, numeric comparisons, and boolean logic. The query system enables powerful library searches and filtering.

3

4

## Capabilities

5

6

### Query Parsing Functions

7

8

Functions for parsing query strings into Query objects that can be executed against the database.

9

10

```python { .api }

11

def query_from_strings(strings: List[str], model_cls: Type) -> Query:

12

"""

13

Parse a list of query strings into a single Query object.

14

15

Parameters:

16

- strings: List of query string components

17

- model_cls: Item or Album class for context

18

19

Returns:

20

Combined Query object for database execution

21

"""

22

23

def parse_sorted_query(query_string: str, model_cls: Type) -> Tuple[Query, Sort]:

24

"""

25

Parse a query string that may include sort specifications.

26

27

Parameters:

28

- query_string: Complete query string with optional sort

29

- model_cls: Item or Album class for context

30

31

Returns:

32

Tuple of (Query object, Sort object)

33

"""

34

35

def parse_query_part(part: str, model_cls: Type) -> Query:

36

"""

37

Parse a single query component into a Query object.

38

39

Parameters:

40

- part: Single query string component

41

- model_cls: Item or Album class for context

42

43

Returns:

44

Query object for the component

45

"""

46

```

47

48

### Base Query Classes

49

50

Core query interface and base implementations for different query types.

51

52

```python { .api }

53

class Query:

54

"""Base class for all query types."""

55

56

def match(self, item: Union[Item, Album]) -> bool:

57

"""

58

Test whether this query matches an item or album.

59

60

Parameters:

61

- item: Item or Album object to test

62

63

Returns:

64

True if the query matches the object

65

"""

66

67

def clause(self) -> Tuple[str, List[Any]]:

68

"""

69

Generate SQL WHERE clause for database execution.

70

71

Returns:

72

Tuple of (SQL string, parameter list)

73

"""

74

75

class FieldQuery(Query):

76

"""Base class for queries that operate on specific fields."""

77

78

def __init__(self, field: str, pattern: Any, fast: bool = True):

79

"""

80

Initialize field-based query.

81

82

Parameters:

83

- field: Name of the field to query

84

- pattern: Pattern or value to match against

85

- fast: Whether to use fast database operations when possible

86

"""

87

```

88

89

### String Query Types

90

91

Query types for matching text fields with various string comparison methods.

92

93

```python { .api }

94

class StringQuery(FieldQuery):

95

"""Query for exact or partial string matches."""

96

97

def __init__(self, field: str, pattern: str, fast: bool = True):

98

"""

99

Create string matching query.

100

101

Parameters:

102

- field: Field name to search

103

- pattern: String pattern to match (supports wildcards)

104

- fast: Use database string operations when possible

105

"""

106

107

class SubstringQuery(StringQuery):

108

"""Query for substring matches (case-insensitive)."""

109

110

def __init__(self, field: str, pattern: str):

111

"""

112

Create substring matching query.

113

114

Parameters:

115

- field: Field name to search

116

- pattern: Substring to find within field values

117

"""

118

119

class RegexpQuery(FieldQuery):

120

"""Query using regular expressions for pattern matching."""

121

122

def __init__(self, field: str, pattern: str):

123

"""

124

Create regular expression query.

125

126

Parameters:

127

- field: Field name to search

128

- pattern: Regular expression pattern

129

"""

130

```

131

132

### Numeric Query Types

133

134

Query types for numeric comparisons and range operations.

135

136

```python { .api }

137

class NumericQuery(FieldQuery):

138

"""Query for numeric field comparisons."""

139

140

def __init__(self, field: str, point: float, interval: float = 0):

141

"""

142

Create numeric comparison query.

143

144

Parameters:

145

- field: Numeric field name

146

- point: Target value for comparison

147

- interval: Range around target (0 for exact match)

148

"""

149

150

class DateQuery(FieldQuery):

151

"""Query for date/time field comparisons."""

152

153

def __init__(self, field: str, date: str, precision: str = 'day'):

154

"""

155

Create date comparison query.

156

157

Parameters:

158

- field: Date field name (year, month, day, added, mtime)

159

- date: Date string in various formats

160

- precision: Precision level ('year', 'month', 'day')

161

"""

162

163

class DurationQuery(FieldQuery):

164

"""Query for duration/length field comparisons."""

165

166

def __init__(self, field: str, duration: str):

167

"""

168

Create duration comparison query.

169

170

Parameters:

171

- field: Duration field name (typically 'length')

172

- duration: Duration string (e.g., '3:30', '210s')

173

"""

174

```

175

176

### Boolean Logic Queries

177

178

Query types for combining multiple queries with logical operations.

179

180

```python { .api }

181

class AndQuery(Query):

182

"""Query that matches when ALL subqueries match."""

183

184

def __init__(self, subqueries: List[Query]):

185

"""

186

Create AND logic query.

187

188

Parameters:

189

- subqueries: List of Query objects that must all match

190

"""

191

192

class OrQuery(Query):

193

"""Query that matches when ANY subquery matches."""

194

195

def __init__(self, subqueries: List[Query]):

196

"""

197

Create OR logic query.

198

199

Parameters:

200

- subqueries: List of Query objects, any of which can match

201

"""

202

203

class NotQuery(Query):

204

"""Query that matches when subquery does NOT match."""

205

206

def __init__(self, subquery: Query):

207

"""

208

Create NOT logic query.

209

210

Parameters:

211

- subquery: Query object to negate

212

"""

213

```

214

215

### Special Query Types

216

217

Additional query types for specific use cases and edge conditions.

218

219

```python { .api }

220

class TrueQuery(Query):

221

"""Query that always matches (returns all items)."""

222

223

def match(self, item: Any) -> bool:

224

return True

225

226

class FalseQuery(Query):

227

"""Query that never matches (returns no items)."""

228

229

def match(self, item: Any) -> bool:

230

return False

231

232

class PathQuery(FieldQuery):

233

"""Query for filesystem path matching with platform-aware comparisons."""

234

235

def __init__(self, field: str, pattern: str):

236

"""

237

Create path matching query.

238

239

Parameters:

240

- field: Path field name (typically 'path')

241

- pattern: Path pattern with filesystem-appropriate separators

242

"""

243

244

class CollectionQuery(Query):

245

"""Query for matching items within specific collections or playlists."""

246

247

def __init__(self, collection_name: str):

248

"""

249

Create collection membership query.

250

251

Parameters:

252

- collection_name: Name of collection to match against

253

"""

254

```

255

256

## Query Language Syntax

257

258

### Basic Field Matching

259

260

```python

261

# Field equals value

262

items = lib.items('artist:Beatles')

263

items = lib.items('year:1969')

264

265

# Field contains substring

266

items = lib.items('title:love')

267

268

# Case-insensitive matching is default

269

items = lib.items('artist:beatles') # Matches "Beatles"

270

```

271

272

### Wildcards and Patterns

273

274

```python

275

# Wildcards (* and ?)

276

items = lib.items('artist:*Beatles*') # Contains "Beatles"

277

items = lib.items('title:Hey?') # "Hey" followed by one char

278

279

# Regular expressions (prefix with ~)

280

items = lib.items('artist:~(Beatles|Rolling Stones)')

281

items = lib.items('title:~^Love') # Starts with "Love"

282

```

283

284

### Numeric Comparisons

285

286

```python

287

# Exact values

288

items = lib.items('year:1969')

289

items = lib.items('track:5')

290

291

# Ranges (inclusive)

292

items = lib.items('year:1960..1970') # 1960 to 1970

293

items = lib.items('length:180..240') # 3-4 minutes

294

295

# Comparisons

296

items = lib.items('year:..1970') # Up to 1970

297

items = lib.items('year:1980..') # 1980 and later

298

```

299

300

### Date Queries

301

302

```python

303

# Specific dates

304

items = lib.items('added:2024-01-01')

305

items = lib.items('mtime:2024-01-01..2024-01-31')

306

307

# Relative dates

308

items = lib.items('added:1d..') # Added in last day

309

items = lib.items('added:1w..') # Added in last week

310

items = lib.items('added:1m..') # Added in last month

311

```

312

313

### Boolean Logic

314

315

```python

316

# AND (default when multiple terms)

317

items = lib.items('artist:Beatles year:1969')

318

319

# OR (comma-separated)

320

items = lib.items('artist:Beatles,Stones')

321

322

# NOT (prefix with -)

323

items = lib.items('artist:Beatles -album:Anthology')

324

325

# Grouping with parentheses

326

items = lib.items('(artist:Beatles year:1960..1970) genre:Rock')

327

```

328

329

### Path Queries

330

331

```python

332

# Path contains

333

items = lib.items('path:/music/rock/')

334

335

# Path patterns

336

items = lib.items('path:*.flac') # FLAC files only

337

items = lib.items('path:~/Music/*') # In Music directory

338

```

339

340

## Query Usage Examples

341

342

### Library Queries

343

344

```python

345

from beets.library import Library

346

from beets.dbcore.queryparse import query_from_strings, parse_sorted_query

347

348

lib = Library('/path/to/library.db', '/music')

349

350

# Simple queries

351

rock_items = lib.items('genre:Rock')

352

recent_albums = lib.albums('added:2024..')

353

354

# Complex queries

355

query_parts = ['artist:Beatles', 'year:1960..1970', '-album:Anthology']

356

beatles_60s = lib.items(' '.join(query_parts))

357

358

# Sorted queries

359

query, sort = parse_sorted_query('artist:Beatles year+', lib.Item)

360

sorted_items = lib.items(query, sort)

361

```

362

363

### Programmatic Query Building

364

365

```python

366

from beets.dbcore.query import AndQuery, StringQuery, NumericQuery

367

368

# Build queries programmatically

369

artist_query = StringQuery('artist', 'Beatles')

370

year_query = NumericQuery('year', 1969)

371

combined = AndQuery([artist_query, year_query])

372

373

# Use with library

374

items = lib.items(combined)

375

```

376

377

### Custom Query Types

378

379

```python

380

from beets.dbcore.query import FieldQuery

381

382

class GenreQuery(FieldQuery):

383

"""Custom query for genre matching with normalization."""

384

385

def __init__(self, field: str, genre: str):

386

# Normalize genre names

387

normalized = genre.lower().replace('-', ' ')

388

super().__init__(field, normalized)

389

390

def match(self, item):

391

item_genre = item.genre.lower().replace('-', ' ')

392

return self.pattern in item_genre

393

394

# Register custom query type

395

from beets.dbcore.queryparse import query_classes

396

query_classes['genre'] = GenreQuery

397

```

398

399

## Sort Operations

400

401

```python { .api }

402

class Sort:

403

"""Represents sorting specification for query results."""

404

405

def __init__(self, field: str, ascending: bool = True):

406

"""

407

Create sort specification.

408

409

Parameters:

410

- field: Field name to sort by

411

- ascending: True for ascending, False for descending

412

"""

413

414

class MultipleSort(Sort):

415

"""Sort by multiple fields in priority order."""

416

417

def __init__(self, sorts: List[Sort]):

418

"""

419

Create multi-field sort.

420

421

Parameters:

422

- sorts: List of Sort objects in priority order

423

"""

424

```

425

426

### Sort Syntax

427

428

```python

429

# Single field sorts

430

items = lib.items('artist:Beatles', sort='year+') # Ascending by year

431

items = lib.items('artist:Beatles', sort='year-') # Descending by year

432

433

# Multiple field sorts

434

items = lib.items('genre:Rock', sort='artist+ year-') # Artist asc, year desc

435

```

436

437

## Error Handling

438

439

```python { .api }

440

class InvalidQueryError(Exception):

441

"""Raised when query string cannot be parsed."""

442

443

class InvalidSortError(Exception):

444

"""Raised when sort specification is invalid."""

445

```

446

447

Common query errors:

448

- Invalid field names

449

- Malformed regular expressions

450

- Invalid date formats

451

- Syntax errors in complex queries