Query DSL: filters cannot express ranges on a single property (e.g., date windows)
## Summary The query DSL's `filters` object is keyed by property name, so it cannot express two conditions on the same property. In practice this means you cannot ask for a value to fall in a range — most commonly, a date window like "created between A and B". ## Example A natural query — "issues created in April 2026" — would look like this: ```json { "filters": { "created_at": {"op": "gte", "value": "2026-04-01T00:00:00Z"}, "created_at": {"op": "lt", "value": "2026-05-01T00:00:00Z"} } } ``` But the second `created_at` key silently overrides the first (the body validates as JSON, but the second wins), so the engine evaluates only one bound. The compiler does not reject this either — the user gets back a result that looks valid but is not what they asked for. The same constraint applies to numeric ranges (`weight between X and Y`, `diff_size between X and Y`, etc.). ## Why it matters Anything bucketed over time has to be either: 1. Fetched as raw rows and bucketed client-side — capped at 1000 rows per query and tedious to paginate over large projects (e.g., `gitlab-org/gitlab` has 340k+ issues), or 2. Approximated by running N cumulative queries (`>= boundary`) and differencing consecutive results client-side. I used approach (2) for a recent monthly chart of `gitlab-org/gitlab` issues since 2021. It worked, but required 132 queries (66 month boundaries × 2 query shapes) plus rate-limit backoff, where a single range-filter query per month would have sufficed. ## Proposal Add a way to express ranges on a single property. A few shapes that would solve this: - A `between` operator: `{"created_at": {"op": "between", "value": ["2026-04-01...", "2026-05-01..."]}}` - Allow an array of `PropertyFilter` objects under one property: `{"created_at": [{"op": "gte", ...}, {"op": "lt", ...}]}` - Top-level `and`/`or` composition over filter objects. Of these, an array of `PropertyFilter` under one key feels closest to the existing schema and would cover all the common cases (date windows, numeric ranges, exclusive/inclusive bounds). ## Workaround for current users If the property is monotonic with the data (like `created_at`), the cumulative-then-diff trick works: ``` count_in_month(M) = count(created_at >= start_of_M) - count(created_at >= start_of_next_M) ``` It is more queries than necessary, but it is correct.
issue