Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question: ElasticsearchClient.Bulk with object array containing Deserialized JSON #1464

Closed
JamieDixon opened this issue Jun 23, 2015 · 10 comments

Comments

@JamieDixon
Copy link

Hi there.

I'm trying to use the bulk API and am hitting a problem with the way dynamic entries are being handled. It looks like it's a serialization issue.

Given the following:

var bulkEntries = new List<object>();
var bulkEntry = new {index = new { _index = "ourIndex", _type = "ourType", _id = "ourId"}}
bulkEntries.Add(bulkEntry);

Here's two examples, one that works as expected and one that doesn't:

Working

bulkEntries.Add(new { id = 1 });

Not working

var doc = JsonConvert.DeserializeObject<dynamic>(document);
doc.someprop = "some value";

bulkEntries.Add(doc);

In the second example, when we call:

var bulkResponse = client.Bulk(bulkEntries);

The response looks like:

Request: {"index":{"_index":"ourIndex","_type":"ourType","_id":"ourId"}}
[[[]],[[]]]

I'm probably just doing something wrong. Any pointers would be appreciated.

Thank you.

@gmarz
Copy link
Contributor

gmarz commented Jun 23, 2015

@JamieDixon I can't quite reproduce this- works fine for me. Can you share the string (document) that you are deserializing?

@JamieDixon
Copy link
Author

@gmarz The document string is coming from a test and so it looks like "{ \"id\" : \"3\" }"

@gmarz
Copy link
Contributor

gmarz commented Jun 23, 2015

Hmm, okay. Wanted to make sure it didn't contain invalid json or anything funky that would throw off serialization.

Still can't reproduce this. I'm going to add a test, maybe you can take a look at it and see if you can get it to fail/repro?

@JamieDixon
Copy link
Author

Thanks. I'll take a look once you've added the test. Cheers for the help.

gmarz added a commit that referenced this issue Jun 23, 2015
@gmarz
Copy link
Contributor

gmarz commented Jun 23, 2015

^^ @JamieDixon. The expected json is in Issue1464.json.

@JamieDixon
Copy link
Author

Your tests pass just fine. The only possible difference I can see at the moment is the version of elastic search. We're using 1.1.1 with lucene 4.7. Perhaps that makes a difference?

@JamieDixon
Copy link
Author

Ok, I'm getting somewhere now. I've got it working but I don't really know why the broken version doesn't work. Here's the differences:

##Broken

var client = new ElasticsearchClient(new ConnectionSettings(new Uri("http://example.com"), defaultIndex: "foo"));

var bulkResponse = client.Bulk(bulkEntries);

##Working

var client = new ElasticClient(new ConnectionSettings(new Uri("http://example.com"), defaultIndex: "foo"));

var bulkResponse = client.Raw.Bulk(bulkEntries);

The working version is using ElasticClient with client.Raw.Bulk. The broken version uses ElasticsearchClient with client.Bulk.

@gmarz
Copy link
Contributor

gmarz commented Jun 23, 2015

Okay, now that makes sense...this is a difference in the serializer that's being used.

Elasticsearch.Net (ElasticsearchClient) uses SimpleJson for handling serialization. This is embedded in the client and allows the library to be dependency-free.

When ElasticsearchClient is used via the Raw property on ElasticClient, Newtonsoft.Json is used as the serializer instead.

This is possibly a bug in the SimpleJson library, considering we do have dynamic support enabled. We'll need to look into this further.

However, if you're already using NEST (ElasticClient) and have a reference to it, then it's best to just access the low-level client via Raw for stuff like this.

@wbsimms
Copy link
Contributor

wbsimms commented Jun 23, 2015

@gmarz Thanks for this analysis. Any suggestions on how we get the IBulkResponse object from the Raw.Bulk response.

Another observation:

This fails too with the same deserialization issues.

var request = new SearchRequest() {...};
elasticClient.Serializer.Serialize(request);

@Mpdreamz
Copy link
Member

When you call:

var doc = JsonConvert.DeserializeObject<dynamic>(document); the dynamic is actually a Json.NET JObject. If you pass that to the SimpleJson serilazer it sees it as an IEnumerable.

You need to call client.Serializer.Deserialize<dynamic>() instead to give SimpleJson a fair fight! I updated gmarz tests to showcase this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants