2017-05-05 119 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; 
});