Во-первых, будьте осторожны с фильтрацией всего.Основывайте доступные фильтры на потребностях пользователей и расширяйте их в зависимости от спроса.Меньше кода для написания, меньше сложности, меньше индексов на стороне БД, лучшая производительность.
Тем не менее, подход, который я использую для страниц со значительным количеством фильтров, заключается в использовании серверной части перечисления, где мойПоля критериев передаются обратно их значения перечисления (число), чтобы предоставить по запросу.Таким образом, поле фильтра будет содержать имя, значения по умолчанию или применимые значения и значение перечисления, которое будет использоваться при передаче введенного или выбранного значения обратно в поиск.Запрашивающий код создает объект JSON с примененными фильтрами и Base64 для отправки в запросе:
Т.е.
{
p1: "Jake",
p2: "8"
}
Строка запроса выглядит следующим образом: .../api/customer/search?filters=XHgde0023GRw....
На стороне сервера я извлекаю Base64, а затем анализирую его как Dictionary<string,string>
для подачи на анализ фильтра.Например, учитывая, что критерии были для поиска ребенка по имени и возрасту:
// this is the search filter keys, these (int) values are passed to the search client for each filter field.
public enum FilterKeys
{
None = 0,
Name,
Age,
ParentName
}
public JsonResult Search(string filters)
{
string filterJson = Encoding.UTF8.GetString(Convert.FromBase64String(filters));
var filterData = JsonConvert.DeserializeObject<Dictionary<string, string>>(filterJson);
using (var context = new TestDbContext())
{
var query = context.Children.AsQueryable();
foreach (var filter in filterData)
query = filterChildren(query, filter.Key, filter.Value);
var results = query.ToList(); //example fetch.
// TODO: Get the results, package up view models, and return...
}
}
private IQueryable<Child> filterChildren(IQueryable<Child> query, string key, string value)
{
var filterKey = parseFilterKey(key);
if (filterKey == FilterKeys.None)
return query;
switch (filterKey)
{
case FilterKeys.Name:
query = query.Where(x => x.Name == value);
break;
case FilterKeys.Age:
DateTime birthDateStart = DateTime.Today.AddYears((int.Parse(value) + 1) * -1);
DateTime birthDateEnd = birthDateStart.AddYears(1);
query = query.Where(x => x.BirthDate <= birthDateEnd && x.BirthDate >= birthDateStart);
break;
}
return query;
}
private FilterKeys parseFilterKey(string key)
{
FilterKeys filterKey = FilterKeys.None;
Enum.TryParse(key.Substring(1), out filterKey);
return filterKey;
}
Вы можете использовать строки и константы, чтобы избежать анализа перечисления, однако я считаю, что перечисления читаемы и сохраняют отправленную полезную нагрузку внемного компактнее.Выше приведен упрощенный пример и, очевидно, требуется проверка ошибок.Код реализации для сложных условий фильтрации, таких как возраст до даты рождения, лучше подойдет как отдельный метод, но он должен дать вам некоторые идеи.Например, вы можете искать детей по имени, и / или возрасту, и / или имени родителя.