|
1 | | -# Searches |
2 | | -Search Filter Specifier Pattern |
| 1 | +# RoyalCode SmartSearch |
| 2 | + |
| 3 | +## Overview |
| 4 | + |
| 5 | +RoyalCode SmartSearch is a set of .NET libraries for implementing advanced search, filtering, sorting, and data projection in enterprise applications, following the Specification/Filter-Specifier-Pattern. The goal is to facilitate the creation of reusable, decoupled, and extensible search components, integrating with ORMs such as Entity Framework. |
| 6 | + |
| 7 | +## Applied Pattern |
| 8 | + |
| 9 | +The core pattern is the **Filter-Specifier-Pattern** (Specification Pattern), which allows you to define filters and search criteria declaratively, compose LINQ expressions, and simplify testing and maintenance. The main components are: |
| 10 | + |
| 11 | +- **Filter:** Object representing search criteria. |
| 12 | +- **Specifier:** Function or component that applies the filter to a LINQ query. |
| 13 | +- **Selector:** Projection from entities to DTOs. |
| 14 | +- **Sorting:** Sorting of results. |
| 15 | + |
| 16 | +## Libraries |
| 17 | + |
| 18 | +### RoyalCode.SmartSearch.Core |
| 19 | +Abstract components for search and filtering using LINQ and the Specification Pattern. |
| 20 | + |
| 21 | +### RoyalCode.SmartSearch.Linq |
| 22 | +Implements property resolution, expression generation, selector mapping, and dynamic sorting. |
| 23 | + |
| 24 | +### RoyalCode.SmartSearch.EntityFramework |
| 25 | +Integration with Entity Framework Core, adding services and extensions to register entities and perform persistent searches. |
| 26 | + |
| 27 | +### RoyalCode.SmartSearch.Abstractions |
| 28 | +Interfaces and contracts for results, sorting, projection, and search criteria. |
| 29 | + |
| 30 | +## Main Components |
| 31 | + |
| 32 | +### ICriteria<TEntity> |
| 33 | +Interface for defining search criteria, applying filters, sorting, and collecting results: |
| 34 | + |
| 35 | +```csharp |
| 36 | +var criteria = provider.GetRequiredService<ICriteria<SimpleModel>>(); |
| 37 | +criteria.FilterBy(new SimpleFilter { Name = "B" }); |
| 38 | +var results = criteria.Collect(); // Returns only records with Name = "B" |
| 39 | +``` |
| 40 | + |
| 41 | +### ISearchManager<TDbContext> |
| 42 | +Search manager for a DbContext, allowing you to create criteria for entities: |
| 43 | + |
| 44 | +```csharp |
| 45 | +var manager = provider.GetRequiredService<ISearchManager<MyDbContext>>(); |
| 46 | +var criteria = manager.Criteria<MyEntity>(); |
| 47 | +``` |
| 48 | + |
| 49 | +### Sorting and ResultList |
| 50 | +Allows sorting and paging of results, as well as projection to DTOs: |
| 51 | + |
| 52 | +```csharp |
| 53 | +var sorting = new Sorting { OrderBy = "Name", Direction = ListSortDirection.Ascending }; |
| 54 | +criteria.OrderBy(sorting); |
| 55 | +ResultList<MyEntity> result = ...; |
| 56 | +var items = result.Items; |
| 57 | +``` |
| 58 | + |
| 59 | +### Search Configuration |
| 60 | +Use ISearchConfigurations to configure filters, sorting, and selectors: |
| 61 | + |
| 62 | +```csharp |
| 63 | +services.AddEntityFrameworkSearches<MyDbContext>(cfg => |
| 64 | +{ |
| 65 | + cfg.Add<MyEntity>(); |
| 66 | + cfg.AddOrderBy<MyEntity, string>("Name", x => x.Name); |
| 67 | + cfg.AddSelector<MyEntity, MyDto>(x => new MyDto { Id = x.Id, Name = x.Name }); |
| 68 | +}); |
| 69 | +``` |
| 70 | + |
| 71 | +## Usage Examples |
| 72 | + |
| 73 | +### 1. Simple Search with Filter |
| 74 | +```csharp |
| 75 | +public class SimpleModel { public int Id; public string Name; } |
| 76 | +public class SimpleFilter { public string Name; } |
| 77 | + |
| 78 | +var criteria = provider.GetRequiredService<ICriteria<SimpleModel>>(); |
| 79 | +criteria.FilterBy(new SimpleFilter { Name = "B" }); |
| 80 | +var results = criteria.Collect(); // Returns only records with Name = "B" |
| 81 | +``` |
| 82 | + |
| 83 | +### 2. Asynchronous Search |
| 84 | +```csharp |
| 85 | +var results = await criteria.FilterBy(new SimpleFilter { Name = "A" }).CollectAsync(); |
| 86 | +``` |
| 87 | + |
| 88 | +### 3. Dynamic Sorting |
| 89 | +```csharp |
| 90 | +criteria.OrderBy(new Sorting { OrderBy = "Name", Direction = ListSortDirection.Descending }); |
| 91 | +var results = criteria.Collect(); |
| 92 | +``` |
| 93 | + |
| 94 | +### 4. Projection to DTO |
| 95 | +```csharp |
| 96 | +criteria.Select<MyDto>(); // Projects to the configured DTO |
| 97 | +``` |
| 98 | + |
| 99 | +### 5. Advanced Filter Configuration |
| 100 | +```csharp |
| 101 | +cfg.ConfigureSpecifierGenerator<MyEntity, MyFilter>(opt => |
| 102 | +{ |
| 103 | + opt.For(f => f.SomeProperty).Predicate(val => e => e.Collection.Any(x => x.Id == val)); |
| 104 | +}); |
| 105 | +``` |
| 106 | + |
| 107 | +## Tests and Examples |
| 108 | +Tests in `RoyalCode.SmartSearch.Tests` demonstrate usage scenarios such as: |
| 109 | +- Filtering by simple and complex properties |
| 110 | +- Sorting and paging |
| 111 | +- Projection to DTOs |
| 112 | +- Custom filter configuration |
| 113 | + |
| 114 | +## References |
| 115 | +- [Specification Pattern](https://martinfowler.com/apsupp/spec.pdf) |
| 116 | +- LINQ, Entity Framework Core |
| 117 | + |
| 118 | +--- |
| 119 | + |
| 120 | +For more examples, see the test files in the `RoyalCode.SmartSearch.Tests` folder. |
0 commit comments