2014-11-04 94 views
7

我正在構建一個基本上允許用戶構建文檔的API應用程序,該文檔可以按照他們想要的結構進行構建,並將存儲在Elasticsearch中。實質上,我爲用戶提供了一個簡單的界面來訪問我們的Elasticsearch實例。我試圖儘可能簡化實現。以下是我正在處理的內容。 使用NEST索引動態對象

的預期體的對象:

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; } 
} 

簡單實現:

[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); 
} 

這工作得很好,但它包含索引,類型和編號源。我真正想做的只是在索引時提供這三個信息,但實際上只是索引document.Document,它是一個動態類型。但是,這似乎與巢到不同意,因爲它會引發在IDE和在編譯時的誤差:

「匿名函數或方法組不能被用作動態綁定操作的組成值」

「不能首先將lambda表達式作爲參數傳遞給委託或表達式樹類型」。

我該如何索引document.Document?有沒有比使用動態類型更好的方式處理未知結構的傳入JSON文檔?

回答

15

有幾種方法可以做到這一點。

嘗試將文檔索引爲動態類型將不起作用,但您可以通過IndexRequest對象將其作爲對象索引。

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); 

或者,如果處理的文件在散裝

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(或更準確地,Elasticsearch.Net)也具有附接到ElasticClient類.RAW方法變體,其可以索引原始JSON 。使用Raw.Index()讓我們做這樣的事情:

string documentJson = JsonConvert.SerializeObject(document.Document); 

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

對該響應的類型描述符是你期待的迴應是在類型(字符串意味着你將有一個序列化JSON響應這你可以反序列化並做一些事情)。這允許我們避開整個對象類型問題,並且NEST完全按照預期將文檔索引到Elasticsearch。

+0

我希望Raw.Index保留新索引中舊索引的父子關係 – Adrian 2015-11-26 02:11:17

+0

作爲'dynamic'的替代方法,我已經使用了'Dictionary '或從類繼承。警告:如果您從'Dictionary'繼承,NEST將不會自動映射文檔上的其他屬性(而是將它們放入字典中)。這對於可變屬性也很有效:常見屬性進入POCO屬性,變量屬性進入「Data」屬性(類型爲「Dictionary ')。這種批量方法很容易使用。不要忘記調用'Bulk'來檢查'.Errors'等等! – nothingisnecessary 2018-01-09 18:39:53