How do you debug your queries in Nest?

I am new to Nest, and I most likely do not create my request, as it seems to me. My question is more about how to teach a person how to fish, and not give me fish. However, as an example, I will take advantage of my current problem.

I have several documents in an ElasticSearch of type Series . I will disable it below without attributes and public modifiers only with information related to the request:

 class Series { string Id {get; set;} DateTime StartDate {get; set;} DateTime EndDate {get; set;} HashSet<Role> ReleasableTo {get; set;} } 

They are all beautiful and dandy. I can Get() a Series object without problems. The problem I am facing is trying to figure out how Nest formats my request. My immediate goal is to find the latest Series , which can be divided into Role.Visitor . I installed the Nest request as follows:

 ISearchResponse<Series> response = client .Search<Series>(r => r.Filter(f => f.Term<Role>(t=>t.ReleasableTo.First(), Role.Visitor)) .SortDescending(ser => ser.EndDate).Size(1)); 

In my opinion, this should produce a query that filters the series, so only those that are ReleasableTo my Role.Visitor are taken into account, reverse sorts by end date and limit the results to one returned. That would be exactly what I want. In the several thousand records that I have for Series, about 90% correspond to this profile. Unfortunately, the query returns 0 results. No mistake, just no results. I don’t know if I am using the API incorrectly, if Nest creates a query structure that does not make sense, or I just don’t know ElasticSearch enough. When I delete the Filter clause, I get the result, but I am not guaranteed that everyone is allowed to see it.

How to view the JSON that Nest ElasticSearch produces and sends?

+11
c # elasticsearch nest
source share
7 answers

You can get the values ​​of the search query URL and the body of the JSON request as follows:

 var requestURL = response.RequestInformation.RequestUrl; var jsonBody = Encoding.UTF8.GetString(response.RequestInformation.Request); 

You can find other useful properties in RequestInformation for debugging.

+13
source share

I like to do this even further than bsarkar offers and eliminates the need for a circuit:

 var client = new ElasticClient(); var seriesSearch = new SearchDescriptor<Series>(); seriesSearch.Filter(f => f .Term<Role>(t => t.ReleasableTo.First(), Role.Visitor)) .SortDescending(ser => ser.EndDate) .Size(1)); string searchJson = Encoding.UTF8.GetString(client.Serializer.Serialize(seriesSearch)); 

Note that your ElasticClient does not need any connection properties, so you have no dependency on ES node.

+7
source share

NEST is the baroque .NET API. For level 2.1+ by call level:

 IElasticClient client = new ElasticClient(); var searchDescriptor = new SearchDescriptor<Series>(); var query = Query<Series>.Term(...); var pretty = query.ToPrettyString(query); var json = client.ToRawRequest(searchDescriptor.Query(descriptor => query)); 

At configuration level:

  var settings = new ConnectionSettings() .PrettyJson().DisableDirectStreaming() .OnRequestCompleted(details=> Debug.WriteLine(Encoding.UTF8.GetString(details.RequestBodyInBytes))); 

By response level, view CallDetails.RequestBodyInBytes .

Used extensions:

  /// <summary> /// Converts search to raw JSON request for debugging. /// </summary> /// <typeparam name="T">The type.</typeparam> /// <param name="self">The self.</param> /// <param name="searchDescriptor">The search descriptor.</param> /// <returns>The string.</returns> public static string ToRawRequest<T>(this IElasticClient self, SearchDescriptor<T> searchDescriptor) where T : class { using (var output = new MemoryStream()) { self.Serializer.Serialize(searchDescriptor, output); output.Position = 0; var rawQuery = new StreamReader(output).ReadToEnd(); return rawQuery; } } /// <summary> /// Prints query into string. /// </summary> /// <param name="self">The self.</param> /// <returns>The value.</returns> public static string ToPrettyString(this QueryContainer self) { using (var settings = new ConnectionSettings()) { var visitor = new DslPrettyPrintVisitor(settings); self.Accept(visitor); return visitor.PrettyPrint.Replace(Environment.NewLine, string.Empty); } } 
+7
source share

Really easy. If this is my code that is looking for:

 var results = client.Search<SearchItem>(s => s.AllIndices() .Query(q => q.Term(p => p.LastName, searchItem.LastName) && q.Term(p => p.FirstName, searchItem.FirstName) && q.Term(p => p.ApplicationCode, searchItem.ApplicationCode) ) .Size(1000) ); var list = results.Documents.ToList(); 

Then I set a breakpoint on the line above. Then, in Visual Studio Immediate Window, I enter this:

 ?results.ConnectionStatus 

and this gives me the following:

 {StatusCode: 200, Method: POST, Url: http://localhost:9200/_all/searchitem/_search, Request: { "size": 1000, "query": { "bool": { "must": [ { "term": { "lastName": { "value": "carr" } } }, { "term": { "firstName": { "value": "adrian" } } } ] } } } 

Hope this helps.

+6
source share

Using the latest 5+ elastic search, I was able to get mine (thanks to Adrian Carr's method) with the following:

 var jsonOutput = System.Text.Encoding.UTF8.GetString( response.ApiCall.RequestBodyInBytes ) 

Which gave me the following result:

 { "from":0, "size":0, "query":{ "bool":{ ... } } } 
+4
source share

You can use EnableTrace or ConnectionStatusHandler . More details here .

+1
source share

Tested in slot 6.2.0

Now you can simply do:

 #if DEBUG connectionSettings.EnableDebugMode(details => { Logger.Debug($"ES Request: {Encoding.UTF8.GetString(details.RequestBodyInBytes ?? new byte[0])}"); Logger.Verbose($"ES Response: {Encoding.UTF8.GetString(details.ResponseBodyInBytes ?? new byte[0])}"); }); #endif 

A call to EnableDebugMode will automatically call DisableDirectStreaming , PrettyJson , and then OnRequestCompleted , passing in the function that you gave it.

NOTE. There may be a mistake somewhere in their answer. For some reason, the answer does not seem to have some closing brackets.

+1
source share

All Articles