Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
180 views
in Technique[技术] by (71.8m points)

c# - Index a dynamic object using NEST

I am building an API application that essentially allows a user to build a document, which can be structured however they want, that will be stored in Elasticsearch. Essentially, I'm providing a simple interface for users to access our Elasticsearch instance. I'm trying to keep the implementation as simple as possible. Here's what I'm dealing with so far.

The 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 it includes the Index, Type, and Id in the source. What I'd really like to do is simply provide those three pieces of information when indexing, but actually just index document.Document, which is of a dynamic type. But, that seems to disagree with Nest, as it throws an error in the IDE and at compile time:

"An anonymous function or method group cannot be used as a constituent value of a dynamically bound operation"

"Cannot use a lambda expression as an argument to a dynamically dispatched operation without first casting it to a delegate or expression tree type".

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

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

There's a couple ways to do this.

Trying to index the document as type dynamic won't work, but you can index it as an object through the 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 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 accurately, Elasticsearch.Net) also has a .Raw method variant attached to the ElasticClient class, which can index raw JSON. Using Raw.Index() let's us do things like this:

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 you'll expect the response to be in (string means you'll have a serialized json response which you can deserialize and do something with). This allows us to sidestep the entire object type issue and NEST indexes the document into Elasticsearch exactly as expected.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...