Reputation: 2911
I have found similar questions both here as well as on the Elastic discussion forum, but unfortunately none of the answers helped.
I am currently using ElasticSearch 7.0
.
I want to make a bulk request to my ElasticSearch server. My JSON file contains information that looks something like this:
{ "index": { "_index": "website", "_id": "link1" }}
{ "label": "Link1" }
Each line is terminated by an LF
line break, and there is also an additional LF
line break at the end of the document.
In C#, here is how I make a POST request for my bulk data:
HttpResponseMessage response = await httpClient.PostAsJsonAsync($"http://127.0.0.1:9200/website/_bulk", jsonDocumentContents);
And yet I keep seeing this error message:
{"error":{"root_cause":[{"type":"illegal_argument_exception","reason":"The bulk request must be terminated by a newline [\\n]"}],"type":"illegal_argument_exception","reason":"The bulk request must be terminated by a newline [\\n]"},"status":400}
How can I fix this error?
UPDATE:
A short description of how I read the JSON document contents into the jsonDocumentContents
variable: The JSON document was stored inside a zipped folder, so retrieving it requires unzipping:
ZipArchive archive = new ZipArchive(zippedFolderStream);
foreach (ZipArchiveEntry entry in archive.Entries)
{
string jsonDocumentContents = new StreamReader(entry.Open()).ReadToEnd();
HttpResponseMessage response = await httpClient.PostAsJsonAsync($"http://127.0.0.1:9200/website/_bulk", jsonDocumentContents);
Console.WriteLine(await response.Content.ReadAsStringAsync());
}
UPDATE:
I just made a bulk request with the exact same contents using PostMan, and the request was successful. However, the error message persists when I make the same bulk request in C# using httpClient.PostAsJsonAsync(...)
.
Upvotes: 5
Views: 1421
Reputation: 2911
I got it working by changing my code to the following:
ZipArchive archive = new ZipArchive(zippedFolderStream);
foreach (ZipArchiveEntry entry in archive.Entries)
{
string jsonDocumentContents = new StreamReader(entry.Open()).ReadToEnd();
StringContent content = new StringContent(jsonDocumentContents, Encoding.ASCII, mediaType: "application/json");
HttpResponseMessage response = await httpClient.PostAsync($"http://127.0.0.1:9200/website/_bulk", content);
Console.WriteLine(await response.Content.ReadAsStringAsync());
}
Notice that I am using HttpClient.PostAsync()
instead of HttpClient.PostAsJsonAsync()
, with a StringContent
instance that specifies "application/json"
as its media type.
I looked into the source code for HttpClient
, and noticed that a new instance of JsonMediaTypeFormatter
is created every time HttpClient.PostAsJsonAsync
is called.
Since my POST
requests are successful when I make them through PostMan, the issue must be caused by how PostAsJsonAsync()
is implemented. I suspect, but have not verified, that the problem is due to the default properties in the JsonMediaTypeFormatter
class.
To circumvent the problem I decided to use Http.PostAsync()
with a correctly-configured StringContent
instance.
Lo and behold, I can now send bulk requests to my ElasticSearch server using C#.
Upvotes: 7