Add simple introspection functions.
Do not ask index with redundant predicates.

We used to send the entire AST to the query where it got deconstructed into its
individual predicates, and each of which were then processed. This involves a
lot of redundant work if users refine queries, e.g., by adding or removing a
predicate.

We now deconstruct the AST into its predicates at query construction time,
where we can directly reuse existing results from sub trees. The search
component then only sends new predicates to the index.