Returning Raw Json in ElasticSearch NEST query - elasticsearch

I'm doing a small research about a client for elastic search in .net and I found that NEST is one of the most supported solutions for this matter.
I was looking at Nest's docummentation and I couldn´t find a way to output a raw json from a query and avoid the serialization into an object, because I'm using angularJs in the front end I don´t want to overload the process of sending the information to the client with some unnecessary steps.
......and also I'd like to know how can I overrdide the serialization process?
I found that NEST uses Json.NET which I would like to change for the servicestack json serielizer.
thanks!

Hi Pedro you can do this with NEST
var searchDescriptor = new SearchDescriptor<ElasticSearchProject>()
.Query(q=>q.MatchAll());
var request = this._client.Serializer.Serialize(searchDescriptor);
ConnectionStatus result = this._client.Raw.SearchPost(request);
Assert.NotNull(result);
Assert.True(result.Success);
Assert.IsNotEmpty(result.Result);
This allows you to strongly type your queries, but return the string .Result which is the raw response from elasticsearch as string to your
request can be an object or the string so if you are OK with the internal json serialize just pass searchDescriptor directly

Use RequestResponseSerializer instead of Serializer.
var searchDescriptor = ...;
...
byte[] b = new byte[60000];
using (MemoryStream ms = new MemoryStream(b))
{
this._client.RequestResponseSerializer.Serialize(searchDescriptor , ms);
}
var rawJson = System.Text.Encoding.Default.GetString(b);

Related

Why is elasticsearch's Nest lowlevel Search method ignoring type and index name defined in SearchDescriptor<>() object

NEST/Elasticsearch.Net version:5.6.5
Elasticsearch version:5.4.3
We are trying to fetch result from our index using the LowLevelClient. We are using the below SearchAsync API
var searchDescriptor = new SearchDescriptor<MyType>()
.Type("mytype")
.Index("myindex")
.Query(....)
.Aggregation(ag => ag.Terms(... Aggregation(ag1 => ag1.Min(...TopHits(...)))));
var memoryStream = new MemoryStream();
_client.Serializer.Serialize(searchDescriptor, memoryStream);
var response = await _client.LowLevel.SearchAsync<byte[]>(memoryStream.ToArray()).ConfigureAwait(false);
//_client - instance of Nest.ElasticClient
//Next Step - Deserialize the response
This is giving me results from other indices also(a combination of results from the various indices) and my deserialization is breaking. The client is ignoring type and index name and calling POST /_search API instead of POST /myindex/mytype/_search on the elastic search
Note:
We need to call a lower-level client because we are using a custom deserializer for performance concern
What is the issue here?
Found a workaround
The SearchAsync<>() method have overloaded method _client.LowLevel.SearchAsync<T>(string indexName, string typeName, T t)
Passing the index name and type name will narrow to search to that particular index.
But the question still remains, why it is not taking the index and type name from SearchDescriptor object.

How to include json as a query parameter in Zapier app

I am trying to create a Zapier app to create a new invoice in Zoho.
Has the requirements: Content-Type: application: x-www-form-urlencoded and input JSON string should be passed using JSONString parameter
The following URI is working for me in REST console when I set the Content Type to "application/x-www-form-urlencoded" and method POST.
https://invoice.zoho.com/api/v3/invoices?authtoken=xxxxxx&organization_id=xxxxxx&JSONString={"customer_id":"xxxxxx","line_items":[{"item_id":"xxxxxx"}]}
However my problem is trying to implement this into Zapier. I think I need to use a function like below to convert the JSON into the right format, but I have no idea how to turn this into a query paramater called JSONString.
create_invoice_pre_write: function(bundle) {
var data = JSON.parse(bundle.request.data);
bundle.request.data = $.param(data);
bundle.request.headers['Content-Type'] = 'application/x-www-form-urlencoded';
return bundle.request;
}
Just need a point in the right direction. I'm not sure what to try next.
You can create an Invoice in Zoho Invoice through Zapier using the below snippet of code.
You can set the query params in bundle.request.params which you want to send it to ZI for the creation of Invoice.
create_invoice_pre_write: function(bundle)
{
var data = JSON.parse(bundle.request.data);
bundle.request.method = "POST",
bundle.request.url = "https://invoice.zoho.com/api/v3/invoices",
bundle.request.params.authtoken = {authtoken},
bundle.request.params.organization_id = {organization_id},
bundle.request.params.JSONString = data
bundle.request.headers= "'Content-Type':'application/x-www-form-urlencoded'";
return bundle.request;
}
This should be working for you. If you have any doubts do let me know.

creating ISearchResponse<T> from json string for unit test

is there a way I can create ISearchResponse to simulate return by elastic search from JSON string? I need to write unittests for my API. The API building the query has histogram, date filters etc and hence response will be as per that and I want to simulate that.
Thanks
You can deserialize json into an instance of ISearchResponse<T> with
ISearchResponse<T> searchResponse = null;
using (var stream = File.OpenRead("path-to-json.json"))
{
searchResponse = client.Serializer.Deserialize<SearchResponse<T>>(stream);
}
If this is stub data, I'd be more inclined to have a stub implementation of ISearchResponse<T> in code as opposed to deserializing json to create an instance; maybe a little easier to maintain.

Get raw query from NEST client

Is it possible to get the raw search query from the NEST client?
var result = client.Search<SomeType>(s => s
.AllIndices()
.Type("SomeIndex")
.Query(query => query
.Bool(boolQuery => BooleanQuery(searchRequest, mustMatchQueries)))
);
I'd really like to debug why I am getting certain results.
The methods to do this seem to change with each major version, hence the confusing number of answers. If you want this to work in NEST 6.x, AND you want to see the deserialized request BEFORE it's actually sent, it's fairly easy:
var json = elasticClient.RequestResponseSerializer.SerializeToString(request);
If you're debugging in Visual Studio, it's handy to put a breakpoint right after this line, and when you hit it, hover over the json variable above and hit the magnifying glass thingy. You'll get a nice formatted view of the JSON.
You can get raw query json from RequestInformation:
var rawQuery = Encoding.UTF8.GetString(result.RequestInformation.Request);
Or enable trace on your ConnectionSettings object, so NEST will print every request to trace output
var connectionSettings = new ConnectionSettings(new Uri(elasticsearchUrl));
connectionSettings.EnableTrace(true);
var client = new ElasticClient(connectionSettings);
NEST 7.x
Enable debug mode when creating settings for a client:
var settings = new ConnectionSettings(connectionPool)
.DefaultIndex("index_name")
.EnableDebugMode()
var client = new ElasticClient(settings);
then your response.DebugInformation will contain information about request sent to elasticsearch and response from elasticsearch. Docs.
For NEST / Elasticsearch.NET v6.0.2, use the ApiCall property of the IResponse object. You can write a handy extension method like this:
public static string ToJson(this IResponse response)
{
return Encoding.UTF8.GetString(response.ApiCall.RequestBodyInBytes);
}
Or, if you want to log all requests made to Elastic, you can intercept responses with the connection object:
var node = new Uri("https://localhost:9200");
var pool = new SingleNodeConnectionPool(node);
var connectionSettings = new ConnectionSettings(pool, new HttpConnection());
connectionSettings.OnRequestCompleted(call =>
{
Debug.Write(Encoding.UTF8.GetString(call.RequestBodyInBytes));
});
In ElasticSearch 5.x, the RequestInformation.Request property does not exist in ISearchResponse<T>, but similar to the answer provided here you can generate the raw query JSON using the Elastic Client Serializer and a SearchDescriptor. For example, for the given NEST search query:
var results = elasticClient.Search<User>(s => s
.Index("user")
.Query(q => q
.Exists(e => e
.Field("location")
)
)
);
You can get the raw query JSON as follows:
SearchDescriptor<User> debugQuery = new SearchDescriptor<User>()
.Index("user")
.Query(q => q
.Exists(e => e
.Field("location")
)
)
;
using (MemoryStream mStream = new MemoryStream())
{
elasticClient.Serializer.Serialize(debugQuery, mStream);
string rawQueryText = Encoding.ASCII.GetString(mStream.ToArray());
}
Before making Request, from Nest Query - For Nest 5.3.0 :
var stream = new System.IO.MemoryStream();
elasticClient.Serializer.Serialize(query, stream );
var jsonQuery = System.Text.Encoding.UTF8.GetString(stream.ToArray());
Edit: It's changed from from Nest 6.x, and you can do below:
var json = elasticClient.RequestResponseSerializer.SerializeToString(request);
on nest version 6 use
connextionString.DisableDirectStreaming();
then on response.DebugInformation you can see all information.
Use result.ConnectionStatus.Request.
When using NEST 7 and you don't want to enable debug mode.
public static string GetQuery<T>(this IElasticClient client, SearchDescriptor<T> searchDescriptor) where T : class
{
using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
{
client.RequestResponseSerializer.Serialize(searchDescriptor, ms);
return Encoding.UTF8.GetString(ms.ToArray());
}
}
While it's possible to get raw request/response through code, I find it much easier to analyze it with fiddler.
The reason is that I can easily analyze raw request, response, headers, Full URL, execution time - all together without any hassle of code changes.
Here's some reference links in case someone unfamiliar with fiddler wants to check details:
#1 https://www.elastic.co/guide/en/elasticsearch/client/net-api/current/logging-with-fiddler.html
#2 NEST 1.0: See request on Fiddler
#3 https://newbedev.com/how-to-get-nest-to-work-with-proxy-like-fiddler
How about using Fiddler ?! :)

Windows phone: what to do with webresponse object?

I am trying to create a simple rss feed reader. I got this webresponse object but how to extract text,links from this?
WebResponse response = request.EndGetResponse(result);
Also,can anyone tell me what is the underlying framework behind all the working of windows phone 8.Is it known as Silverlight?I want to know it so that I can make relevant Google searches and don't bother you people time and again?
It depends on what you want to do with it. You will need to get the Stream and then from there can turn it into a string (or other primitive type), just Json.Net to convert from json to an object, or you can use the stream to create an image.
using (var response = webRequest.EndGetResponse(asyncResult))
{
using (var reader = new StreamReader(response.GetResponseStream()))
{
// need a string?
string result = reader.ReadToEnd();
// Need to convert from json?
MyObject obj = Newtonsoft.Json.JsonConvert.DeserializeObject<MyObject>(result);
}
}

Resources