Dynamic Object Index Using NEST

I am creating an API application that essentially allows the user to create a document that can be structured, however they want to be stored in Elasticsearch. Essentially, I provide a simple interface for user access to our Elasticsearch instance. I try to make the implementation as simple as possible. Here is what I mean so far.

Object for the expected body:

public class DocumentModel { public string Index { get; set; } public string Type { get; set; } public string Id { get; set; } [ElasticProperty(Type = FieldType.Nested)] public dynamic Document { get; set; } } 

Simple implementation:

 [HttpPost] [Route("")] public IHttpActionResult Post(DocumentModel document) { Uri nodeLocation = new Uri("http://localhost:9200"); IConnectionPool connectionPool = new SniffingConnectionPool(new List<Uri> { nodeLocation }); ConnectionSettings settings = new ConnectionSettings(connectionPool); ElasticClient esClient = new ElasticClient(settings); IIndexResponse result = esClient.Index(document, i => i .Index(document.Index) .Type(document.Type) .Id(document.Id)); return Ok(result.IsValid); } 

This works fine, but includes the index, type, and identifier in the source. What I really would like to do is simply provide these three pieces of information when indexing, but actually just index the document.Document, which is of a dynamic type. But this does not seem to be consistent with Nest, as it causes an error in the IDE and at compile time:

"An anonymous function or group of methods cannot be used as the composite value of a dynamically linked operation"

"It is not possible to use a lambda expression as an argument for a dynamically dispatched operation without first entering it into the delegate class or expression tree."

How can I index only document.Document ? Is there a better way to process an incoming JSON document of unknown structure than using a dynamic type?

+7
c # asp.net-web-api elasticsearch nest
source share
1 answer

There are several ways to do this.

Attempting to index a document as dynamic will not work, but you can index it as an object through an IndexRequest object.

 dynamic dynamicDoc = new { /*fill in document format here*/ }; ElasticClient esClient = new ElasticClient(esSettings); IndexRequest<object> request = new IndexRequest<object>(dynamicDoc) { Index = "someindex", Type = "SomeType", Id = "someid" }; esClient.Index<object>(request); 

Or if you are dealing with documents in bulk

 List<dynamic> Documents = new List<dynamic>(); //Populate Documents BulkDescriptor descriptor = new BulkDescriptor(); foreach(var doc in Documents) { descriptor.Index<object>(i => i .Index("someindex") .Type("SomeType") .Id("someid") .Document(doc)); } esClient.Bulk(descriptor); 

NEST (or, more precisely, Elasticsearch.Net) also has a .Raw variant attached to the ElasticClient class, which can index raw JSON. Using Raw.Index (), let's do the following:

 string documentJson = JsonConvert.SerializeObject(document.Document); ElasticsearchResponse<string> result = esClient.Raw.Index(document.Index, document.Type, document.Id, documentJson); 

The type descriptor for the response is the type in which you are expecting a response (a string means you will have a json serialized response that you can deserialize and do something about). This circumvents the whole problem of an object type, and NEST indexes the document in Elasticsearch exactly as expected.

+16
source share

All Articles