Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
194 changes: 102 additions & 92 deletions src/Nest/Search/Search/SearchResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,94 +8,99 @@ namespace Nest
{
public interface ISearchResponse<T> : IResponse where T : class
{
/// <summary>
/// Gets the meta data about the shards on which the search query was executed.
/// </summary>
ShardsMetaData Shards { get; }

/// <summary>
/// Gets the meta data about the hits that match the search query criteria.
/// </summary>
HitsMetaData<T> HitsMetaData { get; }

/// <summary>
/// Gets the collection of aggregations
/// </summary>
IReadOnlyDictionary<string, IAggregate> Aggregations { get; }

/// <summary>
/// Gets the results of profiling the search query. Has a value only when
/// <see cref="ISearchRequest.Profile"/> is set to <c>true</c> on the search request.
/// </summary>
Profile Profile { get; }

/// <summary>
/// Gets the aggregations helper that can be used to more easily handle aggregation
/// results.
/// </summary>
AggregationsHelper Aggs { get; }

/// <summary>
/// Gets the suggester results.
/// </summary>
IReadOnlyDictionary<string, Suggest<T>[]> Suggest { get; }

/// <summary>
/// Time in milliseconds for Elasticsearch to execute the search
/// </summary>
long Took { get; }

/// <summary>
/// Gets a value indicating whether the search timed out or not
/// </summary>
bool TimedOut { get; }

/// <summary>
/// Gets a value indicating whether the search was terminated early
/// </summary>
bool TerminatedEarly { get; }

/// <summary>
/// Gets the scroll id which can be passed to the Scroll API in order to retrieve the next batch
/// of results. Has a value only when <see cref="SearchRequest{T}.Scroll"/> is specified on the
/// search request
/// </summary>
string ScrollId { get; }

/// <summary>
/// Gets the total number of documents matching the search query criteria
/// </summary>
long Total { get; }

/// <summary>
/// Gets the maximum score for documents matching the search query criteria
/// </summary>
double MaxScore { get; }

/// <summary>
/// Gets the documents inside the hits, by deserializing <see cref="IHitMetadata{T}.Source"/> into T.
/// <para>NOTE: if you use <see cref="ISearchRequest.StoredFields"/> on the search request,
/// <see cref="Documents"/> will be empty and you should use <see cref="Fields"/>
/// instead to get the field values. As an alternative to
/// <see cref="Fields"/>, try source filtering using <see cref="ISearchRequest.Source"/> on the
/// search request to return <see cref="Documents"/> with partial fields selected
/// </para>
/// </summary>
IReadOnlyCollection<T> Documents { get; }

/// <summary>
/// Gets the collection of hits that matched the query
/// </summary>
/// <value>
/// The hits.
/// </value>
IReadOnlyCollection<IHit<T>> Hits { get; }

/// <summary>
/// Gets the field values inside the hits, when the search request uses
/// <see cref="SearchRequest{T}.StoredFields"/>.
/// </summary>
IReadOnlyCollection<FieldValues> Fields { get; }
/// <summary>
/// Gets the meta data about the shards on which the search query was executed.
/// </summary>
ShardsMetaData Shards { get; }

/// <summary>
/// Gets the meta data about the hits that match the search query criteria.
/// </summary>
HitsMetaData<T> HitsMetaData { get; }

/// <summary>
/// Gets the collection of aggregations
/// </summary>
IReadOnlyDictionary<string, IAggregate> Aggregations { get; }

/// <summary>
/// Gets the results of profiling the search query. Has a value only when
/// <see cref="ISearchRequest.Profile"/> is set to <c>true</c> on the search request.
/// </summary>
Profile Profile { get; }

/// <summary>
/// Gets the aggregations helper that can be used to more easily handle aggregation
/// results.
/// </summary>
AggregationsHelper Aggs { get; }

/// <summary>
/// Gets the suggester results.
/// </summary>
IReadOnlyDictionary<string, Suggest<T>[]> Suggest { get; }

/// <summary>
/// Time in milliseconds for Elasticsearch to execute the search
/// </summary>
long Took { get; }

/// <summary>
/// Gets a value indicating whether the search timed out or not
/// </summary>
bool TimedOut { get; }

/// <summary>
/// Gets a value indicating whether the search was terminated early
/// </summary>
bool TerminatedEarly { get; }

/// <summary>
/// Gets the scroll id which can be passed to the Scroll API in order to retrieve the next batch
/// of results. Has a value only when <see cref="SearchRequest{T}.Scroll"/> is specified on the
/// search request
/// </summary>
string ScrollId { get; }

/// <summary>
/// Gets the total number of documents matching the search query criteria
/// </summary>
long Total { get; }

/// <summary>
/// Gets the maximum score for documents matching the search query criteria
/// </summary>
double MaxScore { get; }

/// <summary>
/// Number of times the server performed an incremental reduce phase
/// </summary>
long NumberOfReducePhases { get; }

/// <summary>
/// Gets the documents inside the hits, by deserializing <see cref="IHitMetadata{T}.Source"/> into T.
/// <para>NOTE: if you use <see cref="ISearchRequest.StoredFields"/> on the search request,
/// <see cref="Documents"/> will be empty and you should use <see cref="Fields"/>
/// instead to get the field values. As an alternative to
/// <see cref="Fields"/>, try source filtering using <see cref="ISearchRequest.Source"/> on the
/// search request to return <see cref="Documents"/> with partial fields selected
/// </para>
/// </summary>
IReadOnlyCollection<T> Documents { get; }

/// <summary>
/// Gets the collection of hits that matched the query
/// </summary>
/// <value>
/// The hits.
/// </value>
IReadOnlyCollection<IHit<T>> Hits { get; }

/// <summary>
/// Gets the field values inside the hits, when the search request uses
/// <see cref="SearchRequest{T}.StoredFields"/>.
/// </summary>
IReadOnlyCollection<FieldValues> Fields { get; }
}

[JsonObject]
Expand All @@ -115,6 +120,7 @@ public class SearchResponse<T> : ResponseBase, ISearchResponse<T> where T : clas
public Profile Profile { get; internal set; }

private AggregationsHelper _agg;

[JsonIgnore]
public AggregationsHelper Aggs => _agg ?? (_agg = new AggregationsHelper(this.Aggregations));

Expand All @@ -140,13 +146,17 @@ public class SearchResponse<T> : ResponseBase, ISearchResponse<T> where T : clas
[JsonProperty(PropertyName = "hits")]
public HitsMetaData<T> HitsMetaData { get; internal set; }

[JsonProperty(PropertyName = "num_reduce_phases")]
public long NumberOfReducePhases { get; internal set; }

[JsonIgnore]
public long Total => this.HitsMetaData?.Total ?? 0;

[JsonIgnore]
public double MaxScore => this.HitsMetaData?.MaxScore ?? 0;

private IReadOnlyCollection<T> _documents;

/// <inheritdoc/>
[JsonIgnore]
public IReadOnlyCollection<T> Documents =>
Expand All @@ -155,6 +165,7 @@ public class SearchResponse<T> : ResponseBase, ISearchResponse<T> where T : clas
.ToList());

private IReadOnlyCollection<IHit<T>> _hits;

[JsonIgnore]
public IReadOnlyCollection<IHit<T>> Hits =>
this._hits ?? (this._hits = this.HitsMetaData?.Hits ?? EmptyReadOnly<IHit<T>>.Collection);
Expand All @@ -163,9 +174,8 @@ public class SearchResponse<T> : ResponseBase, ISearchResponse<T> where T : clas

/// <inheritdoc/>
public IReadOnlyCollection<FieldValues> Fields =>
this._fields ?? (this._fields = this.Hits
.Select(h => h.Fields)
.ToList());

this._fields ?? (this._fields = this.Hits
.Select(h => h.Fields)
.ToList());
}
}