1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
//! Top-K Collectors, with ordering and condition support.
//!
//! This is a collection of collectors that provide top docs
//! rank functionality very similar to `tantivy::TopDocs`, with
//! added support for declaring the ordering (ascending or
//! descending) and collection-time conditions.
//!
//! ```no_run
//! # use tique::conditional_collector::{Descending,TopCollector};
//! # use tantivy::Score;
//! # let condition_for_segment = true;
//! let collector =
//! TopCollector::<Score, Descending, _>::new(10, condition_for_segment);
//! ```
//!
//! NOTE: Usually the score type (`Score` above, a `f32`) is inferred
//! so there's no need to specify it.
//!
//! # Ordering Support
//!
//! When constructing a top collector you *must* specify how to
//! actually order the items: in ascending or descending order.
//!
//! You simply choose `Ascending` or `Descending` and let the
//! compiler know:
//!
//! ```no_run
//! # use tique::conditional_collector::{Ascending,TopCollector};
//! # use tantivy::Score;
//! # let limit = 10;
//! # let condition_for_segment = true;
//! let collector =
//! TopCollector::<Score, Ascending, _>::new(limit, condition_for_segment);
//! ```
//!
//! # Condition Support
//!
//! A "condition" is simply a way to tell the collector that
//! a document is a valid candidate to the top. It behaves
//! just like a query filter would, but does not limit the
//! candidates before the collector sees them.
//!
//! This is a valid condition that accepts everything:
//!
//! ```no_run
//! let condition_for_segment = true;
//! ```
//!
//! Generally speaking, a `condition` is anything that implements
//! the `ConditionForSegment` trait and you can use closures as a
//! shortcut:
//!
//! ```no_run
//! # use tantivy::{Score,SegmentReader};
//! # use tique::conditional_collector::{TopCollector,Ascending};
//! # let limit = 10;
//! let condition_for_segment = move |reader: &SegmentReader| {
//! // Fetch useful stuff from the `reader`, then:
//! move |segment_ord, doc_id, score, is_ascending| {
//! // Express whatever logic you want
//! true
//! }
//! };
//!
//! let collector =
//! TopCollector::<Score, Ascending, _>::new(limit, condition_for_segment);
//! ```
//!
//! ## Aside: Pagination with Constant Memory
//!
//! If you've been using `tantivy` for a while, you're probably
//! used to seeing tuples like `(T, DocAddress)` (T is usually
//! `tantivy::Score`, but changes if you customize the score
//! somehow).
//!
//! You can also use these tuples as a condition and they act
//! like a cursor for pagination, so when you do something like:
//!
//! ```no_run
//! # use tantivy::DocAddress;
//! # use tique::conditional_collector::{TopCollector,Descending};
//! let limit = 10;
//! let condition_for_segment = (0.42, DocAddress{segment_ord: 0, doc_id: 1});
//! let collector =
//! TopCollector::<_, Descending, _>::new(limit, condition_for_segment);
//! ```
//!
//! What you are asking for is the top `limit` documents that appear
//! *after* (because you chose the `Descending` order) documents
//! that scored `0.42` at whatever query you throw at it (and in
//! case multiple docs score the name, the collector knows to
//! break even by the `DocAddress`).
//!
//! The results that you get after your search will contain more
//! `(T, DocAddress)` tuples you can use to keep pagination
//! going without ever having to increase `limit`.
//!
//! Check `examples/conditional_collector_tutorial.rs` for more details.
mod custom_score;
mod top_collector;
pub(crate) mod topk;
mod traits;
pub use top_collector::{CollectionResult, TopCollector};
pub use topk::{Ascending, Descending};
pub use traits::*;