A fluent API that serves as a string builder to provide searching, filtering and sorting capability with using the amazing MeiliSearch, the aim is to provide a fluent interface that works on top of meilisearch-dotnet
This implementation provides a set of bases on which usage can be derived and extended from, the default behavior is described in the following few sections
To sort or filter a model, two attributes must be used in order to index the required properties in MeiliSearch Client
[SearchFilter] attribute to make a property filterable
[Sortable] attribute to enable sorting using a property
To be able to use SearchQueryBuilder, your models must inherit one of these bases
SearchModel the base class for any model
GeoSearchModel : SearchModel is a search model with coordinates search capability
SearchQueryBuilder supports pagination of results on calling evaluate method by passing a PageCriteria object
Evaluate(new PageCriteria(1, 10))
public class Employee : GeoSearchModel<Guid>
{
[SearchFilter]
public string Name { get; set; }
[Sortable]
[SearchFilter]
public int Age { get; set; }
[SearchFilter]
public bool IsDeleted { get; set; }
[Sortable]
[SearchFilter]
public int Salary { get; set; }
[SearchFilter]
public int MonthlyTarget { get; set; }
}
//initiate the client
var client = new MeilisearchClient("http://localhost:7700", "4ebc913989554d17acea2ee981287a26");
//resolve usage of both SearchFilter and Sortable attributes
client.ResolveFluentFiltersFromAssembly(AppDomain.CurrentDomain.GetAssemblies());
//inject the client
builder.Services.AddSingleton(client);
var searchService = new SearchService<Employee>(client);
var searchQuery = new SearchQueryBuilder<Employee>("John") //can discard the search term
.OrderByDesc(x => x.Age) //Sorting Fields
.OrderBy(x => x.Salary)
.WithinRadius(31.222813, 29.951325, 2000) //Filtering by geo models
.Value(x => x.Salary).GreaterThan(2000) //Filtering by logic operators
.Value(x => x.IsDeleted).IsTrue()
.Value(x => x.Age).GreaterThan(29)
.Evaluate(); //Evaluating to Meilisearch search model
var result = await searchService.SearchAsync(searchQuery);
Nuget Installation
Install-Package FluentSearchEngine
Program.cs
// with options
builder.Services.AddSearchQueryBuilder(c =>
{
c.Host = "http://localhost:7700";
c.Key = "API_KEY";
c.CollectiveHubName = "IndexBucket";
c.MaxTotalHits = 999;
c.UseCrossSearch = true;
});
//or default
builder.Services.AddSearchQueryBuilder("http://localhost:7700", "API_KEY");
EmployeesController.cs
[ApiController]
[Route("[controller]")]
public class EmployeesController : ControllerBase
{
private readonly ISearchService<Employee> _searchService;
public EmployeesController(ISearchService<Employee> searchService)
{
_searchService = searchService;
}
[HttpGet("/GetModels")]
public async Task<IActionResult> Get()
{
var searchQuery = new SearchQueryBuilder<Employee>()
.OrderByDesc(x => x.Age)
.Value(x => x.Salary).LowerThan(3000)
.Value(x => x.IsDeleted).IsFalse()
.Value(x => x.MonthlyTarget).GreaterThanOrEquals(20000)
.Value(x => x.Age).GreaterThan(29)
.Evaluate(new PageCriteria(1, 10));
var result = await _searchService.SearchAsync(searchQuery);
return Ok(result.Hits);
}
}