> For the complete documentation index, see [llms.txt](https://docs.flexbase.in/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.flexbase.in/data-and-providers/data-stores/search-store-full-text/elastic-search.md).

# Elastic Search

## Description

Elasticsearch can be used as the backing implementation for Flex full-text search. Your application code should depend on `IFlexSearchStore`, while Flex provides the provider bridge and wiring.

## Important concepts

* **`IFlexSearchStore` is the contract**: app code performs searches and indexing through the shared interface, not Elastic SDK types.
* **Indexing + searching**: generated plugins typically call `IndexAsync<TDocument>(document)`, and generated queries call `SearchAsync<TDocument>(query, skip, take)`.
* **Provider bridge**: the Elasticsearch implementation is exposed via an `IFlexSearchStoreBridge` internally, but most consumers only need `IFlexSearchStore`.

## Configuration in DI

Add the provider in your DI composition root (commonly in `EndPoints/...CommonConfigs/OtherApplicationServicesConfig.cs` or wherever you centralize registrations).

```csharp
// using Sumeru.Flex; // IFlexSearchStore

public static class OtherApplicationServicesConfig
{
	public static IServiceCollection AddOtherApplicationServices(
		this IServiceCollection services,
		IConfiguration configuration)
	{
		// Registers Elasticsearch as the IFlexSearchStore bridge.
		// Flex auto-wires generated Queries/Plugins that *use* IFlexSearchStore.
		services.AddFlexElasticsearchSearchStore(configuration);

		return services;
	}
}
```

## appsettings.json

Configuration is read from `FlexBase:DataStores:Search:Elasticsearch`.

```json
{
  "FlexBase": {
	"DataStores": {
	  "Search": {
		"Elasticsearch": {
		  "NodeUri": "http://localhost:9200",
		  "Username": null,
		  "Password": null,
		  "ApiKey": null,
		  "IndexName": "your-index-name"
		}
	  }
	}
  }
}
```

## Examples (template-based)

These examples mirror the generated Query and PostBus plugin templates. You do **not** register these types manually—Flex discovers and wires generated Queries/Handlers/Plugins automatically.

### Search a single document (Query)

```csharp
using Microsoft.Extensions.Logging;
using Sumeru.Flex;
using System.Linq;
using System.Threading.Tasks;

namespace {YourApplication}.Queries.Search;

public class SearchArticlesGetSingle : FlexiQueryBridgeAsync<ArticleDto>
{
	protected readonly ILogger<SearchArticlesGetSingle> _logger;
	protected readonly IFlexHost _flexHost;
	protected readonly IFlexSearchStore _searchStore;
	protected SearchArticlesGetSingleParams _params;
	protected FlexAppContextBridge _flexAppContext;

	public SearchArticlesGetSingle(ILogger<SearchArticlesGetSingle> logger, IFlexHost flexHost, IFlexSearchStore searchStore)
	{
		_logger = logger;
		_flexHost = flexHost;
		_searchStore = searchStore;
	}

	public virtual SearchArticlesGetSingle AssignParameters(SearchArticlesGetSingleParams @params)
	{
		_params = @params;
		return this;
	}

	public virtual async Task<ArticleDto?> Fetch()
	{
		_flexAppContext = _params.GetAppContext();

		var results = await _searchStore.SearchAsync<ArticleSearchDocument>(
			_params.Query,
			take: 1);

		var first = results.FirstOrDefault();
		// TODO: map ArticleSearchDocument -> ArticleDto
		return first as ArticleDto;
	}
}

public class SearchArticlesGetSingleParams : DtoBridge
{
	public string Query { get; set; }
}

public class ArticleSearchDocument
{
	public string Id { get; set; }
}
```

### Index a document (PostBus plugin)

```csharp
using Microsoft.Extensions.Logging;
using Sumeru.Flex;
using System.Threading.Tasks;

namespace {YourApplication}.PostBus.Search;

public partial class IndexArticleInSearchPlugin : FlexiPluginBase, IFlexiPlugin<IndexArticlePostBusPacket>
{
	protected string EventCondition = "";

	protected readonly ILogger<IndexArticleInSearchPlugin> _logger;
	protected readonly IFlexHost _flexHost;
	protected readonly IFlexSearchStore _searchStore;
	protected readonly IArticleSearchMapper _mapper;

	protected ArticleSearchDocument? _model;
	protected FlexAppContextBridge? _flexAppContext;

	public IndexArticleInSearchPlugin(
		ILogger<IndexArticleInSearchPlugin> logger,
		IFlexHost flexHost,
		IFlexSearchStore searchStore,
		IArticleSearchMapper mapper)
	{
		_logger = logger;
		_flexHost = flexHost;
		_searchStore = searchStore;
		_mapper = mapper;
	}

	public virtual async Task Execute(IndexArticlePostBusPacket packet)
	{
		_flexAppContext = packet.Cmd.Dto.GetAppContext();  //do not remove this line

		_model = _mapper.MapToSearchDocument(packet.Cmd.Dto);
		await _searchStore.IndexAsync<ArticleSearchDocument>(_model);

		await this.Fire(EventCondition, packet.FlexServiceBusContext);
	}
}

public interface IArticleSearchMapper
{
	ArticleSearchDocument MapToSearchDocument(object dto);
}
```

## Elasticsearch considerations

* Configure exactly one authentication approach: `ApiKey` or `Username`/`Password`.
* `IndexName` should be a stable physical index name (consider aliases/rollovers operationally).
