Reputation: 64
I want to index a collection of dynamic objects using the ElasticSearch Nest Client. The objects are first materialized by NewtonsoftJson.NET from a JSON file into dynamic objects and then manipulated by the program. All objects get a property "Id". This should serve as "_id" field for ElasticSearch. The "_id" field must be the same for identical data records in order to be able to update data later. Because attributes "IdProperty" cannot be added to a dynamic object and a mapping can also not be used, I was forced to the following solution. I would like to keep the dynamic objects because I manipulate only a few properties and the other properties are of no interest to me.
var values = new List<dynamic>();
dynamic obj = new System.Dynamic.ExpandoObject();
obj.Id = "ABC";
obj.SomeValue0 = "12";
obj.SomeValue1 = 99;
values.Add(obj);
var descriptor = new BulkDescriptor();
// Now i want to Index this List
foreach (var doc in values) {
// Here the StackOverflowException will be thrown
descriptor.Index<object>(i => i
.Index("abc")
.Id(doc.Id)
.Document(doc));
}
client.Bulk(descriptor);
(Index a dynamic object using NEST - This was my inspiration)
This example raises a StackOverflow exception during indexing. It does not matter whether one or more objects are in the list.
Interestingly, the following method works without problems. The only thing that doesn't work is the ElasticSearch "_id" field was generated automatically and therefore does not correspond to the "Id" field.
client.IndexMany(value, index);
What am I doing wrong with the first possibility and is there a possibility to set a "_id" on a dynamic object?
Upvotes: 0
Views: 2615
Reputation: 125498
You need to
Id
property to string
(or Nest.Id
if it could be another type with an implicit conversion to Nest.Id
, for example, Guid
object
Here's an example
var client = new ElasticClient();
var values = new List<dynamic>();
dynamic obj = new System.Dynamic.ExpandoObject();
obj.Id = "ABC";
obj.SomeValue0 = "12";
obj.SomeValue1 = 99;
values.Add(obj);
var descriptor = new BulkDescriptor();
// Now i want to Index this List
foreach (var doc in values)
{
descriptor.Index<object>(i => i
.Index("abc")
.Id((Id)doc.Id)
.Document((object)doc));
}
client.Bulk(descriptor);
which will send a request like the following
POST http://localhost:9200/_bulk
{"index":{"_index":"abc","_type":"object","_id":"ABC"}}
{"Id":"ABC","SomeValue0":"12","SomeValue1":99}
Dynamic types don't play nicely with generic types and member access expressions, which looks to be related to runtime type resolution. In the example above, I would recommend using anonymous types and a List<object>
Upvotes: 4