JsonPathQuery
A compiled RFC 9535 JSONPath query, applied to one document the caller is already holding.
val document = Variant.fromJson("""{"items":[{"sku":"a","qty":1},{"sku":"b","qty":5}]}""")
val query = JsonPathQuery.compile("$.items[?@.sku == 'b' && @.qty > 2]")
query.forEachNodeIn(document) { println(it.toJsonSummaryString()) }
// $['items'][1] {"qty":5,"sku":"b"}What this answers that nothing else in the engine does. CatalogPath.forEachNodeIn answers where is this path; an index answers which documents hold a value. Neither can express which elements satisfy a condition, and until this module the answer was a walk every caller wrote by hand — differently each time. $.. is the other half: a location shape here does not have to know how deeply the data nests, which is what a self-recursive document needs.
It cannot change which documents a query returns, by construction. This module sits beside the storage chain rather than in it: nothing in rabosh-core, rabosh-index, rabosh-query or rabosh-api depends on it, so no plan, no bound and no posting list can reach this grammar. That matters because RFC 9535's comparison rules and the engine's Predicate rules genuinely disagree — $.a == 1 over {"a":[1,2]} is false in both and for different reasons, ! here complements the node while Not there complements the document — and two definitions of comparison are a defect exactly when both can decide the same question. Here they cannot.
Conformance, stated at the strength of its evidence. The grammar, the selectors, the descendant segment, the filter selector and all five function extensions are implemented and checked against the JSONPath Compliance Test Suite: all 703 of its cases run and pass, with nothing excluded and the corpus's shape asserted before any case does. match and search are answered by an RFC 9485 I-Regexp matcher written for this module — a Thompson construction, so it costs the pattern times the subject and never backtracks, which is what makes a filter safe to run over a corpus with a pattern that came from the data.
Immutable and thread-safe. Compiling is the expensive half and holding the result is the point of the name — a query re-parsed per document is what this API exists to stop. One instance may be applied to any number of documents from any number of threads at once.
See also
for the lifetime rule the results carry.
Functions
Every node document holds at this query's locations, in RFC 9535's nodelist order.
The same, materialised.