# Postgre Sql Full Text Search

## Description

PostgreSQL full-text search can be used as the backing implementation for Flex search operations. 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.
* **Search configuration**: PostgreSQL uses a text search configuration (for example `english`) to control tokenization and stemming.
* **Provider bridge**: the PostgreSQL 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 PostgreSQL full-text search as the IFlexSearchStore bridge.
		// Flex auto-wires generated Queries/Plugins that *use* IFlexSearchStore.
		services.AddFlexPostgreSqlSearchStore(configuration);

		return services;
	}
}
```

## appsettings.json

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

```json
{
  "FlexBase": {
	"DataStores": {
	  "Search": {
		"PostgreSql": {
		  "ConnectionString": "Host=...;Database=...;Username=...;Password=...",
		  "SearchConfiguration": "english"
		}
	  }
	}
  }
}
```

## 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 paged list (Query)

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

namespace {YourApplication}.Queries.Search;

public class SearchArticlesPaged : FlexiQueryPagedListBridgeAsync<SearchArticlesPagedParams, ArticleDto, FlexAppContextBridge>
{
	protected readonly ILogger<SearchArticlesPaged> _logger;
	protected readonly IFlexHost _flexHost;
	protected readonly IFlexSearchStore _searchStore;
	protected SearchArticlesPagedParams _params;
	protected FlexAppContextBridge _flexAppContext;

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

	public virtual SearchArticlesPaged AssignParameters(SearchArticlesPagedParams @params)
	{
		_params = @params;
		return this;
	}

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

		var skip = (_params.PageNumber - 1) * _params.PageSize;
		var results = await _searchStore.SearchAsync<ArticleSearchDocument>(
			_params.Query,
			skip: skip,
			take: _params.PageSize);

		var list = results.ToList();
		// TODO: map ArticleSearchDocument -> ArticleDto, and compute true totalCount if supported
		return new PagedResult<ArticleDto>
		{
			Items = list as IEnumerable<ArticleDto>,
			TotalCount = list.Count,
			PageNumber = _params.PageNumber,
			PageSize = _params.PageSize
		};
	}
}

public class SearchArticlesPagedParams : DtoBridge
{
	public string Query { get; set; }
	public int PageNumber { get; set; } = 1;
	public int PageSize { get; set; } = 20;
}

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

## PostgreSQL considerations

* Ensure your database/table setup supports full-text indexes for your data shape.
* `SearchConfiguration` should match the language/analyzer behavior you expect (for example `simple` vs `english`).
