I have upgraded to ElasticSearch.Net /Nest 2.0.2 and I can no longer use the low level client method (connector.GetClient().Raw.Bulk()). I have looked at the documentation but I can't seem to find any that shows how to post raw json using the new version to index new documents.
That how I do that:
var client = new Elasticsearch.Net.ElasticLowLevelClient();
var result = client.Index<object>("index", "type", "id", new Elasticsearch.Net.PostData<object>("{\"name\":\"value\"}"));
client.Raw.Bulk() turned into client.LowLevel.Bulk(). With NEST, you could do something like:
// jsonStringList assumed to hold your bulk indexing commands and objects
var jsonPostData = new PostData<object>(jsonStringList);
var response = nestClient.LowLevel.Bulk<VoidResponse>("your_index", "your_type", jsonPostData);
Related
I've been looking all over the place and haven't been able to find a suitable answer to this question. I've created a NEST client using this code:
var myIndex = "myTestIndex";
var myType = "myTestType";
var myClusterUri= "http://localhost:9200";
var uri = new Uri(myClusterUri);
var settings = new ConnectionSettings(uri);
var client = new ElasticClient(settings);
and then later, using this to make a call to the bulk api.
var myJson = PopulateJsonForBulkAPI();
var rawBulkResult = client.Raw.Bulk(myIndex, myType, myJson);
The problem I'm having is that I'm getting an OutOfMemoryException when making the bulk api call. The method that populates myJson creates a HUGE block of JSON but not big enough to throw the exception (but big enough to throw it, if it were duplicated). Then when I make the call to the bulk api it throws the OutOfMemoryException because NEST holds onto the original request (in essence, duplicating the JSON and not having enough memory to hold onto everything). Is there a way to make the call to the Bulk API but tell NEST to NOT hold onto the original request so the huge block of JSON isn't duplicated in memory?
Edit
I'm using NEST version 1.7.2 and ElasticSearch version 1.7.2
In NEST 1.x, the request bytes are always made available on the response but you could write a HttpConnection implementation that doesn't do this, overriding DoSynchronousRequest and DoAsyncRequest.
If you're getting OutOfMemoryExceptions though, this sounds like you're trying to send too much data in one bulk request. Consider splitting up the data into batches of bulk requests.
I'm trying to send a POST request and format the query string in a specific format. Order doesn't matter aside from the first parameter, but I haven't been successful.
What I need:
localhost/someapp/api/dosomething/5335?save=false&userid=66462
What some of my attempts have spit out:
http://localhost/someapp/api/dosomething/?Id=29455&save=false&userId=797979
http://localhost/someapp/api/dosomething/?save=false&userId=797979
How I formatted the request:
request.AddQueryParameter("Id", "29455");
request.AddQueryParameter("save", "false");
request.AddQueryParameter("user", "4563533245");
If I try AddParameterfor Id it doesn't get appended on the query string (I'm thinking because it's a POST and not a GET), so that won't work. The API isn't expecting a form, it's expecting :
(string id, List<Dictionary<string,string>>)
I could use a StringBuilder, but that feels wrong. I'm not sure if UrlSegment is the best way to go either, since I would basically be hacking the query string. Is there a way to format my request in the format I need using RestSharp's API?
What I ended up using is UrlSegment and then kept the .AddQueryParameter methods, so the final code block looks like :
var url = new RestClient(localhost/someapp/api/dosomething/{id});
var request = new RestRequest(Method.POST);
request.AddParameter("Id", "5335", ParameterType.UrlSegment);
request.AddQueryParameter("save", "true");
request.AddQueryParameter("UserId", "5355234");
Which produced the URI I needed.
The easiest coding process for using RestSharp or any other API client library would be to use Postman to generate if you are unsure of how to code it. Download Postman, do a new request, enter the URL string to send to the API, click on Code, select C# (RestSharp) from the dropdown. Here is the code it generated.
var client = new RestClient("http://localhost/someapp/api/dosomething /5335?save=false&userid=66462");
var request = new RestRequest(Method.POST);
request.AddHeader("Postman-Token", "bd05aa45-f1b9-4665-a3e7-888ad16f2800");
request.AddHeader("cache-control", "no-cache");
IRestResponse response = client.Execute(request);
I am a complete newbie to webservices but have some experience in Java. We have been provided with Liverail API documentation with a list of Entities that we can consume. This is what their doc says:
"Logical flow An API client must always use the /login method followed by the /set/entity method. All the remaining APIcalls will be executed on the selected entity. If you need to switch the current entity, you should use /unset/entity followed by a new /set/entity with the new entity ID as parameter. It is also recommended to call /logout once the API client ends its execution"
XML response format
The LiveRail API XML response is always formated like bellow.
My dilema is that i dont know how to make the GET calls.
What i would like to do in java is :
Create a http login to API webservices
Fetch a list of data (response is in XML format)
3 Convert this XML response into CSV file.
Any help will be highly appreciated.
Why not using RestTemplate?
final String uri = "http://localhost:8080/springrestexample/employees/{id}";
Map<String, String> params = new HashMap<String, String>();
params.put("id", "1");
RestTemplate restTemplate = new RestTemplate();
EmployeeVO result = restTemplate.getForObject(uri, EmployeeVO.class, params);
System.out.println(result);
Here is for more tutorials http://howtodoinjava.com/2015/02/20/spring-restful-client-resttemplate-example/
In a particular case I need to be able to disable compression in the requst/response.
Using Firefox RestClient I am able to post some xml to a web service and get some response xml successfully with a single header parameter "Accept-Encoding" : " "
which if I do not set this header, the response body would come back compressed with some binary data in the response body(that's why I want to disable gzip in response)
Now using the same header value in my app (using RestSharp in C#), I still get the binary data (gzip) in response.
Can someone please shed some light? Is it supported in RestSharp?
RestSharp does not support disabling compression.
If you look at the source code in Http.Sync.cs line 267 (assuming a sync request, async has the same code duplicated in Http.Async.cs line 424)
webRequest.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip | DecompressionMethods.None;
that is, the underlying WebRequest that Restsharp uses to make the http call has the compression options hardcoded. There is an open issue that documents this
The feature (only just) seems to have been added, but stealthily - without a note on the issue's status nor on the changelogs. Possibly as it hasn't been sufficiently tested?
Nevertheless I recently had a need for this functionality and tested it - and it works. Just set the RestClient instance's AutomaticDecompression property to false.
If you intend to keep your RestClient instance long-lived remember to do this before its first use - the setting seems to be 'locked in' after use and cannot change after. In my case I needed to make calls with and without AutomaticDecompression so i simply created two different RestClient instances.
Using RestSharp v106.11.4, I was unable to turn off automatic decompression as Bo Ngoh suggested. I set the AutomaticDecompression on the RestClient instance at the moment it gets instantiated, but still the Accept-Encoding header was added.
The way to set this & disable the decompression is through the ConfigureWebRequest method, which is exposed on the RestClient. Below snippet allowed me to turn off this feature:
var client = new RestClient();
client.ConfigureWebRequest(wr =>
{
wr.AutomaticDecompression = DecompressionMethods.None;
});
Not sure if this relevant anymore, but for maybe future references
RestRequest has IList<DecompressionMethods> AllowedDecompressionMethods, and when creating new RestRequest the list is empty. Only when calling the Execute method it fills with the default values (None, Deflate, and GZip) unless it's not empty
To update the wanted decompression method, simply use the method named AddDecompressionMethod and add the wanted decompression method - and that's that
Example:
var client = new RestClient();
var request = new RestRequest(URL, Method.GET, DataFormat.None);
request.AddDecompressionMethod(DecompressionMethods.GZip);
var response = client.Execute(request);
As of RestSharp version 107, the AddDecompressionMethod has been removed and most of the client options has been move to RestClientOptions. Posting here the solution that worked for me, in case anyone needs it.
var options = new RestClientOptions(url)
{
AutomaticDecompression = DecompressionMethods.None
};
_client = new RestClient(options);
In the latest ASP.NET MVC4 beta, how would you support conditional GET support via ETags? The ActionFilter would need to be able to complete the request to generate the ETag for the returned resource in order to compare to the If-None-Match header in the request. And then, regardless of whether the incoming ETag in the If-None-Match header was the same as the generated ETag, add the generated ETag to the ETag response header. But with ASP.NET MVC4, I have no idea where to begin. Any suggestions?
Personally, I'm not a fan of "framework magic" and prefer plain old code in the web methods, else we end up with something more akin to WCF, yuk.
So, within your Get web method, manually create the response like so:
var response = this.Request.CreateResponse(HttpStatusCode.OK, obj);
string hash = obj.ModifiedDate.GetHashCode().ToString();
response.Headers.ETag =
new EntityTagHeaderValue(String.Concat("\"", hash, "\""), true);
return response;
Please note that the ETag produced from the hash code of the timestamp is purely illustrative of a weak entity tagging system. It also shows the additional quotes required.
There is a ETagMessageHandler in the WebApiContrib which does what you need.
UPDATE
I have implemented RFC 2616's server side caching in WebApiContrib. Look for CachingHandler.
More info here.
More Update
This will be actively developed and expanded upon under CacheCow. This will include both client and server components. NuGet packages to be published soon are published now.
WebApiContrib's CachingHandler will still be maintained so any bugs or problems please let me know.
Luke Puplett's answer got me on the right track (+1), but note that you also have to read the ETag on the server side to avoid sending all the data with each request:
string hash = obj.ModifiedDate.GetHashCode().ToString();
var etag = new EntityTagHeaderValue(String.Concat("\"", hash, "\""), true);
if (Request.Headers.IfNoneMatch.Any(h => h.Equals(etag)))
{
return new HttpResponseMessage(HttpStatusCode.NotModified);
}
var response = this.Request.CreateResponse(HttpStatusCode.OK, obj);
response.Headers.ETag = etag;
return response;
It would also be a good idea to respect the If-Modified-Since header. See RFC 2616.
It seems this is what you are looking for (see section "Support for ETags"):
http://blogs.msdn.com/b/webdev/archive/2014/03/13/getting-started-with-asp-net-web-api-2-2-for-odata-v4-0.aspx
In case your model is stored deeper in domain and you are not able to apply the [ConcurrencyCheck] attribute, you can do that using the ODataModelBuilder:
ODataModelBuilder builder = new ODataConventionModelBuilder();
var myEntity = builder.EntitySet<MyEntity>("MyEntities");
myEntity.EntityType.Property(l => l.Version).ConcurrencyToken = true;
this will make it to add the "#odata.etag" property to a response body.