2017-05-05 87 views
0

我期待實現Elastic搜索版本控制功能,以使用NEST庫和C#更新記錄。我實際上希望創建一個幫手,它執行以下操作:Elasticsearch更新與版本控制 - NEST/C#

  1. 閱讀現有記錄。
  2. 對記錄進行更改。
  3. 使用版本功能更新文檔。

我已經完成了一些我的研究,但沒有找到我正在尋找的信息。任何人都可以指出一些代碼示例,實現或測試嗎?

+2

我寫了一個博客張貼的幾年與ES和NEST前約樂觀併發控制的例子:http://forloop.co.uk/blog/optimistic-concurrency-with -elasticsearch-and-nest它使用Elasticsearch 1.x和NEST 1.x,但它在2.x和5.x中基本相同 –

+0

它給了我一個關於如何實現功能的清晰上下文。萬分感謝! –

+0

嗨@RussCam,在你的文章中,我注意到你使用ElasticsearchServerException對象來捕獲和處理重試。出於某種原因,我無法在我的代碼中訪問此對象。我看到ElasticsearchClientException。你能指出如何訪問服務器異常嗎? –

回答

1

我用下面的類其包括版本Update

public class SampleElasticClient 
{ 
    private const string VERSION_CONFLICT_ERROR = "version_conflict_engine_exception"; 

    protected readonly string IndexName; 

    protected readonly ElasticClient Client; 

    public SampleElasticClient(Uri uri, string indexName) 
    { 
     Client = new ElasticClient(new ConnectionSettings(uri).DefaultIndex(indexName)); 
     IndexName = indexName; 
    } 

    public IGetResponse<T> Get<T>(Id id) where T : class 
    { 
     var request = new GetRequest<T>(IndexName, typeof(T), id); 
     var response = Client.Get<T>(request); 
     EnsureSuccessResponse(response); 
     return response; 
    } 

    public void Update<T>(Id id, Func<T, T> update, int retriesCount = 10) where T : class 
    { 
     Retry(() => 
     { 
      var getResponse = Get<T>(id); 
      var item = update(getResponse.Source); 
      return Client.Index(item, index => getResponse.Found 
       ? index.Version(getResponse.Version) 
       : index.OpType(OpType.Create)); 
     }, retriesCount); 
    } 

    protected void EnsureSuccessResponse(IResponse response) 
    { 
     if (!response.IsValid && response.ApiCall.HttpStatusCode != 404) 
     { 
      var errorMessage = response.ServerError != null 
       ? $"ElasticSearch error: {response.ServerError.Error}\r\n" + 
           $"Http status: {response.ServerError.Status}" 
       : $"ElasticSearch error. {response.DebugInformation}"; 
      throw new Exception(errorMessage); 
     } 
    } 

    protected void Retry(Func<IResponse> execute, int retriesCount) 
    { 
     var numberOfRetry = 0; 
     do 
     { 
      var response = execute(); 
      if (response.ServerError?.Error.Type != VERSION_CONFLICT_ERROR || ++numberOfRetry == retriesCount) 
      { 
       EnsureSuccessResponse(response); 
       return; 
      } 
     } while (true); 
    } 
} 

Retry方法負責處理version_conflict_engine_exception和重試更新。 Update方法enther使用lambda插入或更新實體以處理從索引檢索的實體。下面是使用這個類

var client = new SampleElasticClient(new Uri("http://localhost:9200"), indexName); 
var id = 123; 
client.Update<Sample>(id, entity => 
{ 
    if (entity == null) 
     entity = new Sample { Id = id }; // Or any other action for new entity 

    entity.MyField = "new value"; 
    return entity; 
});