v0.6.0 — eight query types promoted, and the hash moves to q3
Coverage goes from 38 native / 21 opaque to 46 / 13 of the 59 query types in the OpenSearch specification. The fingerprint prefix moves q2: → q3:.
Breaking: your fingerprints change
Every hash minted by this version carries the q3: prefix. Dashboards grouping on q2: values will not match new digests — that is what the prefix is for, and it is why all eight promotions ship together rather than one per release: the prefix is global, so promoting a single rare type would invalidate exactly as much as promoting eight.
A signature that did not change keeps its twelve hex characters. All 16 pre-existing fixtures moved their prefix and nothing else:
v0.5.0 q2:fe168406e702
v0.6.0 q3:fe168406e702
So q2:abc… and q3:abc… describe the same shape, and a prefix bump reads as a rename rather than a wall of unrelated values.
What was promoted
| type | before | after |
|---|---|---|
hybrid |
hybrid(?) |
(embedding:knn(k=20) or title:"waterproof hiking boots") |
wrapper |
wrapper(?) |
the decoded query, in full |
combined_fields |
combined_fields(?) |
title|body:"connection timeout" |
common |
common(?) |
msg:timeout |
percolate |
percolate(?) |
alerts:percolate() |
rank_feature |
rank_feature(?) |
popularity:rank_feature() |
distance_feature |
distance_feature(?) |
created_at:distance_feature(pivot=7d) |
intervals |
intervals(?) |
msg:intervals() |
hybrid is the one that matters on a modern cluster. The flagship OpenSearch pattern — a lexical clause and a vector clause combined under a normalisation pipeline — used to collapse into a single word that said nothing about a query whose entire point is what it combines. It returns the union of its queries exactly as dis_max does; the two differ only in how scores are blended, and this library already declines to distinguish scoring:
q=(embedding:knn(k=20) or title:"waterproof hiking boots") q3:a8a542c4af15 (hybrid)
q=(embedding:knn(k=20) or title:"waterproof hiking boots") q3:a8a542c4af15 (dis_max)
wrapper recovers rather than summarises. A query passed through base64 as an opaque blob is decoded and parsed, so it fingerprints identically to the same query sent unwrapped:
{"term":{"env":"prod"}} q3:1cc724ddd8ef
{"wrapper":{"query":"eyJ0ZXJtIjp7ImVudiI6InByb2QifX0="}} q3:1cc724ddd8ef
rank_feature and distance_feature stay leaves rather than unwrapping the way function_score does. They read as boosting and sit where a boost would, but a document without the field does not match — so they genuinely restrict the result set. The scoring curve (saturation, log, sigmoid, and a distance origin) is dropped: it reorders, it does not exclude.
intervals keeps the field only — modelling all_of/any_of/max_gaps/ordered would be a parser inside the parser for the rarest type that has a field at all. percolate keeps the field, which says which set of saved queries is being replayed; its indexed-document variant gets the same warning a terms lookup does. combined_fields and common reuse the paths multi_match and fuzzy already take.
What stays opaque, and why that is now settled
The 13 remaining types are a position, not a backlog:
- the
span_*family (9, includingfield_masking_span) — nobody debugs a span query from a log line, and promoting one span without the rest would read worse than promoting none; type— removed with mapping types; no live cluster accepts it;sltr— a Learning-to-Rank plugin absent from the official image, and pure rescoring;template— lives behind/_search/template, not in a query clause;agentic— hands the whole result set to a model deciding outside the DSL.
They are still signalled as type(?), never dropped, and still contribute to the fingerprint.
Certification and compatibility
All eight promoted types were already certified against live clusters, with two documented exceptions: combined_fields is accepted by 3.8.0 and answers unknown query on 2.19.6, and hybrid cannot be probed without a registered search pipeline — its reason is recorded in resources/probes.json.
Runtime requirements are unchanged: php and ext-json, nothing else. Tested on PHP 7.4 through 8.5.
Upgrading
composer require mr-dlef/os-query-digest:^0.6If you store fingerprints, expect q3: on everything minted after the upgrade. Historical q2: values remain correct for the rules that produced them — and where the shape is unchanged, the twelve hex characters let you line the two up.