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 107 108 109 110 111 112 113
use crate::search::*;
use crate::util::*;
/// A `top_hits` metric aggregation keeps track of the most relevant document being aggregated.
/// This aggregation is intended to be used as a sub aggregation,
/// so that the top matching documents can be aggregated per bucket.
///
/// > We do not recommend using `top_hits` as a top-level aggregation.
/// If you want to group search hits, use the
/// [`collapse`](https://www.elastic.co/guide/en/elasticsearch/reference/current/collapse-search-results.html)
/// parameter instead.
///
/// The `top_hits` aggregation can effectively be used to group result sets
/// by certain fields via a bucket aggregation. One or more bucket aggregations
/// determines by which properties a result set get sliced into.
///
/// <https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-top-hits-aggregation.html>
#[derive(Debug, Clone, Serialize, PartialEq)]
pub struct TopHitsAggregation {
top_hits: TopHitsAggregationInner,
}
#[derive(Debug, Clone, Serialize, PartialEq)]
struct TopHitsAggregationInner {
#[serde(skip_serializing_if = "ShouldSkip::should_skip")]
_source: Option<SourceFilter>,
#[serde(skip_serializing_if = "ShouldSkip::should_skip")]
from: Option<u64>,
#[serde(skip_serializing_if = "ShouldSkip::should_skip")]
size: Option<u64>,
#[serde(skip_serializing_if = "ShouldSkip::should_skip")]
sort: SortCollection,
}
impl Aggregation {
/// Creates an instance of [`TopHitsAggregation`]
pub fn top_hits() -> TopHitsAggregation {
TopHitsAggregation {
top_hits: TopHitsAggregationInner {
_source: None,
from: None,
size: None,
sort: Default::default(),
},
}
}
}
impl TopHitsAggregation {
/// Indicates which source fields are returned for matching documents
pub fn source<T>(mut self, source: T) -> Self
where
T: Into<SourceFilter>,
{
self.top_hits._source = Some(source.into());
self
}
/// The offset from the first result you want to fetch.
pub fn from(mut self, from: u64) -> Self {
self.top_hits.from = Some(from);
self
}
/// The maximum number of top matching hits to return per bucket.
///
/// By default the top three matching hits are returned.
pub fn size(mut self, size: u64) -> Self {
self.top_hits.size = Some(size);
self
}
/// A collection of sorting fields
pub fn sort<T>(mut self, sort: T) -> Self
where
T: IntoIterator,
T::Item: Into<Sort>,
{
self.top_hits.sort.extend(sort);
self
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn serialization() {
assert_serialize_aggregation(Aggregation::top_hits(), json!({ "top_hits": { } }));
assert_serialize_aggregation(
Aggregation::top_hits()
.source(false)
.from(2)
.size(10)
.sort(FieldSort::new("sort_field").order(SortOrder::Desc)),
json!({
"top_hits": {
"_source": false,
"from": 2,
"size": 10,
"sort": [
{ "sort_field": { "order": "desc" } }
]
}
}),
);
}
}