#query #collection #search #predicate #filter

standout-seeker

Generic query engine for filtering Rust struct collections

18 stable releases (4 major)

7.0.0 Feb 17, 2026
6.2.0 Feb 15, 2026
5.0.0 Feb 3, 2026
4.0.0 Feb 2, 2026
3.7.0 Jan 31, 2026

#2106 in Rust patterns

Download history 25/week @ 2026-01-30 85/week @ 2026-02-06 89/week @ 2026-02-13

174 downloads per month
Used in 3 crates (via standout)

MIT license

125KB
2.5K SLoC

Seeker - Generic query engine for filtering Rust struct collections.

Seeker provides a fluent API for building and executing queries against in-memory collections of structs. It supports:

  • Multiple field types: strings, numbers, timestamps, enums, booleans
  • Rich operators: equality, comparison, string matching, regex
  • Clause groups: AND, OR, NOT with fixed combination semantics
  • Multi-field ordering with ascending/descending
  • Pagination with limit and offset

Quick Start

use standout_seeker::{Query, Op, Dir, Value, Number};

// Define your data
struct Task {
    name: String,
    priority: i32,
    archived: bool,
}

// Create an accessor function
fn accessor<'a>(task: &'a Task, field: &str) -> Value<'a> {
    match field {
        "name" => Value::String(&task.name),
        "priority" => Value::Number(Number::I64(task.priority as i64)),
        "archived" => Value::Bool(task.archived),
        _ => Value::None,
    }
}

// Build and execute a query
let tasks = vec![
    Task { name: "Write docs".into(), priority: 3, archived: false },
    Task { name: "Fix bug".into(), priority: 5, archived: false },
    Task { name: "Old task".into(), priority: 1, archived: true },
];

let query = Query::new()
    .and_gte("priority", 3i64)
    .not_eq("archived", true)
    .order_desc("priority")
    .build();

let results = query.filter(&tasks, accessor);
assert_eq!(results.len(), 2);
assert_eq!(results[0].name, "Fix bug");

Query Semantics

Queries combine three clause groups with fixed logic:

match = (all AND clauses match)
      ∧ (at least one OR clause matches, OR no OR clauses exist)
      ∧ (no NOT clause matches)

This provides predictable behavior without complex nesting:

  • AND group: All clauses must match (empty = trivially satisfied)
  • OR group: At least one must match (empty = trivially satisfied)
  • NOT group: None may match (empty = trivially satisfied)

Field Types and Operators

Type Operators
String Eq, Ne, StartsWith, EndsWith, Contains, Regex
Number Eq, Ne, Gt, Gte, Lt, Lte
Timestamp Eq, Ne, Before, After, Gt, Gte, Lt, Lte
Enum Eq, Ne, In
Bool Eq, Ne, Is

Dependencies

~2–3.5MB
~63K SLoC