With nest I am doing a Terms aggregation.
I am also doing an inner TopHits aggregation.
My result give me all results information in the response object except TopHits values which I can read thanks to TopHits() method.
I would like to have tophits values directly in result without using NEST TopHits() method for reading into aggs. I would like to have all datas in info as we have in elastic search classic requests.
This is what I am actually doing:
My aggregation request:
var response = Client.Search<myclass>(s => s
.Type("type")
.Aggregations(a => a
.Terms("code_bucket", t => t
.Field("field_of_aggregation")
.Size(30)
.Order(TermsOrder.CountAscending)
.Aggregations(a2 => a2
.TopHits("code_bucket_top_hits", th => th.Size(20))
)
)));
I receive a result object in which I can access all information except TopHits.
if we examine results we can see TopHits values are stored in private field "_hits":
If I stringify result object , i can see the total number of TopHits, but I can't see the field _hits so i can see the documents:
JavaScriptSerializer js = new JavaScriptSerializer();
string json = js.Serialize(response);
json does not contains topHits result:
I can access to values but i need to use nest method TopHits():
var firstBucket= response.Aggs.Terms("code_bucket");
foreach (var bucket in firstBucket.Buckets)
{
var hits = bucket.TopHits("code_bucket_top_hits");
foreach (var hit in hits.Documents<myclass>())
{
var prop1= hit.prop1;
var prop2= hit.prop2;
}
}
}
But it would be really usefule if i could have all infos in one , like we have when we do elasticsearch request without nest
Do you know if there is a way?
NEST is a higher level abstraction over Elasticsearch that models each request and response with strong types, providing fluent and object initializer syntaxes to build requests, and methods to access portions of the response, without having to handle JSON serialization yourself.
Sometimes however, you might want to manage this yourself, which is what it sounds like you'd like to do. In these cases, Elasticsearch.Net can be used, which is a low level client for Elasticsearch and is unopinionated in how you model your requests and responses.
You can use the client in Elasticsearch.Net instead of NEST, however, the good news is NEST uses Elasticsearch.Net under the covers and also exposes the low level client through the .LowLevel
property on IElasticClient
. Why would you want to use the lowlevel client on NEST as opposed to just using Elasticsearch.Net directly? A major reason to do so is that you can take advantage of strong types for requests and responses when you need to and leverage NEST's usage of Json.NET for serialization, but bypass this and make calls with the low level client when you want/need to.
Here's an example
var client = new ElasticClient();
var searchRequest = new SearchRequest<Question>
{
Size = 0,
Aggregations = new TermsAggregation("top_tags")
{
Field = "tags",
Size = 30,
Order = new[] { TermsOrder.CountAscending },
Aggregations = new TopHitsAggregation("top_tag_hits")
{
Size = 20
}
}
};
var searchResponse = client.LowLevel.Search<JObject>("posts", "question", searchRequest);
// this will be of type JObject. Do something with it
searchResponse.Body
Here, I can use NEST's object initializer syntax to construct a request, but use the low level client to deserialize the response to a Json.NET JObject
. You can deserialize to a T
of your choosing by changing it in client.LowLevel.Search<T>()
. You could for example use
var searchResponse = client.LowLevel.Search<string>("posts", "question", searchRequest);
to return a string, or
var searchResponse = client.LowLevel.Search<Stream>("posts", "question", searchRequest);
to return a stream, etc.