Elasticsearch .NET 客户端 - NEST - 高级客户端 - 索引

索引文件

NEST 将 Elasticsearch 的索引和批量 API 作为方法公开,以启用单个或多个文档的索引。除此之外,客户端还为典型的索引方法提供了一些方便的速记方法。

单一文件

IndexDocument可以分别使用和IndexDocumentAsync方法对单个文档进行同步或异步索引。这些方法是索引单个文档的简单方法,不需要任何额外的请求参数

var person = new Person
{
    Id = 1,
    FirstName = "Martijn",
    LastName = "Laarman"
};

var indexResponse = client.IndexDocument(person); 
if (!indexResponse.IsValid)
{
    // If the request isn't valid, we can take action here
}

var indexResponseAsync = await client.IndexDocumentAsync(person);

返回一个同步方法IndexResponse

Task<IndexResponse>返回一个可以等待的异步方法

**带参数的单个文档

如果您需要在索引时设置额外的参数,您可以使用Index带有 fluent 或对象初始值设定项语法的方法。该Index方法公开了一种设置附加参数的方法,例如要索引的索引名称、分配给文档的 id、路由参数等,从而可以更好地控制索引。

var person = new Person
{
    Id = 1,
    FirstName = "Martijn",
    LastName = "Laarman"
};

var indexResponse1 = client.Index(person, i => i.Index("people")); 

var indexResponse2 = client.Index(new IndexRequest<Person>(person, "people"));

流利的语法

对象初始化语法

 

**多个文档与IndexMany

可以使用IndexManyIndexManyAsync方法分别同步或异步索引多个文档。这些方法特定于 NEST 客户端,以提供使用_bulk端点索引多个文档的便捷快捷方式。

IndexMany单个 HTTP 请求中的所有文档,因此对于非常大的文档集合,不推荐使用此方法 - 请考虑使用BulkAllObservable帮助程序。

var people = new []
{
    new Person
    {
        Id = 1,
        FirstName = "Martijn",
        LastName = "Laarman"
    },
    new Person
    {
        Id = 2,
        FirstName = "Stuart",
        LastName = "Cam"
    },
    new Person
    {
        Id = 3,
        FirstName = "Russ",
        LastName = "Cam"
    }
};

var indexManyResponse = client.IndexMany(people); 

if (indexManyResponse.Errors) 
{
    foreach (var itemWithError in indexManyResponse.ItemsWithErrors) 
    {
        Console.WriteLine($"Failed to index document {itemWithError.Id}: {itemWithError.Error}");
    }
}

// Alternatively, documents can be indexed asynchronously
var indexManyAsyncResponse = await client.IndexManyAsync(people);

返回 IBulkResponse 的同步方法

可以检查响应以查看是否有任何批量操作导致错误

如果有错误,可以枚举和检查

返回可以等待的 Task<IBulkResponse> 的异步方法

 

**多个文档与Bulk

如果您需要更多地控制对许多文档的索引,您可以使用BulkBulkAsync方法并使用描述符来自定义批量调用。

与这些IndexMany方法一样,文档是在单个 HTTP 请求中使用批量 API 发送的。这确实意味着应该考虑 HTTP 请求的整体大小。对于大量文档的索引,执行多个单独的Bulk调用或使用可能是明智的,这可以解决[BulkAllObservable](<https://www.elastic.co/guide/en/elasticsearch/client/net-api/current/indexing-documents.html#bulkall-observable>)很多复杂性。

var bulkIndexResponse = client.Bulk(b => b
    .Index("people")
    .IndexMany(people)
); 

// Alternatively, documents can be indexed asynchronously similar to IndexManyAsync
var asyncBulkIndexResponse = await client.BulkAsync(b => b
    .Index("people")
    .IndexMany(people)
);

 

返回 IBulkResponse 的同步方法,与 IndexMany 相同,可以以相同的方式检查错误

返回可以等待的 Task<IBulkResponse> 的异步方法

可以通过将描述符传递给IndexMany on 方法来控制如何配置每个批量索引操作Bulk。这是一个根据要索引的文档的属性为每个文档指定不同索引和管道的示例

var bulkIndexResponse = client.Bulk(b => b
    .Index("people")
    .IndexMany(people, (descriptor, person) => descriptor
        .Index(person.Id % 2 == 0
            ? "even-index"
            : "odd-index") 
        .Pipeline(person.FirstName.StartsWith("M")
            ? "startswith_m_pipeline"
            : "does_not_start_with_m_pipeline") 
    )
);

 

根据文档为文档配置显式索引Id

指定索引文档时要使用的摄取管道

**BulkAllObservable带有助手的多个文档

使用BulkAllObservable帮助程序可以让您专注于索引的总体目标,而不必担心重试、退避或分块机制。BulkAll可以使用方法和Wait()扩展方法对多个文档进行索引。

此帮助程序公开了在索引失败的情况下自动重试/回退的功能,并控制在单个 HTTP 请求中索引的文档数量。在下面的示例中,每个请求将包含 1000 个文档,从原始输入中分块。如果有大量文档,这可能会导致许多 HTTP 请求,每个请求包含 1000 个文档(最后一个请求可能包含更少,具体取决于总数)。

助手懒惰枚举提供IEnumerable<T>的文档,让你轻松索引大量文档

var bulkAllObservable = client.BulkAll(people, b => b
    .Index("people")
    .BackOffTime("30s") 
    .BackOffRetries(2) 
    .RefreshOnCompleted()
    .MaxDegreeOfParallelism(Environment.ProcessorCount)
    .Size(1000) 
)
.Wait(TimeSpan.FromMinutes(15), next => 
{
    // do something e.g. write number of pages to console
});

重试之间等待多长时间

如果发生故障,尝试了多少次重试

每个批量请求的项目

执行索引并等待长达 15 分钟,而 BulkAll 调用是异步的,这是一个阻塞操作

的内部实现BulkAllObservable是异步的,使用 观察者设计模式使观察者能够注册,以便在返回每个批量响应、发生错误以及BulkAllObservable完成时采取行动。虽然内部实现是异步的,但您通常希望等到所有批量索引完成后再继续。该Wait方法是一种方便的简写方式,使用 aManualResetEvent阻塞当前线程,直到批量索引完成或发生错误。

 

**高级批量索引

助手公开了BulkAllObservable许多方法来进一步控制进程,例如

  • BufferToBulk

    在批量请求被分派到服务器之前自定义单个操作

  • RetryDocumentPredicate

    决定是否应该重试未能被索引的文档

  • DroppedDocumentCallback

    确定在文档未被索引的情况下该怎么做,即使在重试之后

以下示例演示了其中的一些方法,除了使用 aBulkAllObserver订阅批量索引进程并对每个成功的批量响应、发生错误以及进程完成时采取一些操作。

观察者BulkAllObserver不应从其接口实现中抛出异常,例如OnNextOnError。任何抛出的异常都应该不会被处理。鉴于此,在批量索引过程中发生的任何异常都应该被捕获并抛出观察者之外,如下面的示例所示。查看处理异常的 

var bulkAllObservable = client.BulkAll(people, b => b
      .BufferToBulk((descriptor, buffer) => 
      {
          foreach (var person in buffer)
          {
              descriptor.Index<Person>(bi => bi
                  .Index(person.Id % 2 == 0 ? "even-index" : "odd-index") 
                  .Document(person)
              );
          }
      })
      .RetryDocumentPredicate((bulkResponseItem, person) => 
      {
          return bulkResponseItem.Error.Index == "even-index" && person.FirstName == "Martijn";
      })
      .DroppedDocumentCallback((bulkResponseItem, person) => 
      {
          Console.WriteLine($"Unable to index: {bulkResponseItem} {person}");
      }));

var waitHandle = new ManualResetEvent(false);
ExceptionDispatchInfo exceptionDispatchInfo = null;

var observer = new BulkAllObserver(
    onNext: response =>
    {
        // do something e.g. write number of pages to console
    },
    onError: exception =>
    {
        exceptionDispatchInfo = ExceptionDispatchInfo.Capture(exception);
        waitHandle.Set();
    },
    onCompleted: () => waitHandle.Set());

bulkAllObservable.Subscribe(observer); 

waitHandle.WaitOne(); 

exceptionDispatchInfo?.Throw();

 

在分派之前自定义每个批量操作,

将每个文档索引到偶数索引或奇数索引 决定在失败的情况下是否应该重试文档 如果无法索引文档,则调用此委托 订阅 observable,它将启动批量索引过程 阻塞当前线程,直到收到信号 如果在批量索引过程中捕获到异常,则抛出它

posted on 2022-03-09 17:11  春秋路人甲  阅读(356)  评论(0)    收藏  举报