![](https://i0.wp.com/world.optimizely.com/resources/images/SocialShareImage.jpg?w=896&ssl=1)
Введение
Продолжение от Часть 1 – Советы по поискусегодня я поделюсь следующей частью — советами по фильтрам.
В этой статье используются следующие версии платформ: Optimizely CMS 12.27.x, Optimizely Customized Commerce 14.21.x и EpiServer.Find 16.1.x.
Как добавить новый пользовательский фильтр
Во встроенном поиске и навигации Optimizely по умолчанию используются следующие фильтры:
- И Фильтр
- Булевский фильтр
- Фильтр существует
- Фильтр георасстояния
- Фильтр диапазона георасстояний
- Фильтр геополигонов
- Имеет Детский Фильтр
- Фильтр идентификаторов
- Фильтр километров
- Вложенный фильтр
- Не фильтровать
- Или Фильтр
- Фильтр префиксов
- Фильтр запроса
- Фильтр диапазона
- Фильтр скриптов
- Фильтр терминов
Эти фильтры генерируют соответствующий основной текст при отправке запросов в Elasticsearch через фреймворк поиска и навигации с использованием JSON-конвертеров.
Что делать, если фильтр существует в Elasticsearch, но не в Search & Navigation, или существующий фильтр не имеет требуемых параметров? Можно ли создать новый фильтр?
Да, вы можете добавлять новые пользовательские фильтры в Поиск и навигацию. Вот как создать новый фильтр регулярного выражения.
Шаг 1: Создание нового DTO на основе класса фильтра
[JsonConverter(typeof(RegularExpressionFilterConverter))]
public class RegularExpressionFilter : Filter
{
[JsonIgnore]
public string Field { get; set; }
[JsonProperty("value")]
public string Value { get; set; }
public RegularExpressionFilter(string field, string value)
{
Field = field;
Value = value;
}
}
Шаг 2: Создайте новый JSON-конвертер для нового фильтра
internal class RegularExpressionFilterConverter : CustomWriteConverterBase
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
if (value is not RegularExpressionFilter)
{
writer.WriteNull();
return;
}
var regularExpressionFilter = (RegularExpressionFilter)value;
writer.WriteStartObject();
writer.WritePropertyName("regexp");
writer.WriteStartObject();
writer.WritePropertyName(regularExpressionFilter.Field);
serializer.Serialize(writer, regularExpressionFilter.Value);
writer.WriteEndObject();
writer.WriteEndObject();
}
}
Шаг 3: Создайте новый метод фильтрации для вашего поиска
public static DelegateFilterBuilder MatchRegularExpression(this string value, string input)
{
return new DelegateFilterBuilder((string field) => new RegularExpressionFilter(field, input));
}
Шаг 4: Примените новый фильтр к вашему поиску
if (!string.IsNullOrEmpty(filterOptions.Q)){
query = query.Filter(x => x.Name.MatchRegularExpression(filterOptions.Q));
}
Ключевое слово для поиска в этом примере может быть текстом в синтаксисе регулярного выражения. Синтаксис для ElasticSearch можно найти здесь.
Как применить И/ИЛИ для группы подфильтров
Рассмотрим следующий пример:
У вас есть тип контента продукта со следующими свойствами:
[Display(Name = "On sale", GroupName = SystemTabNames.Content, Order = 50)]
public virtual bool OnSale { get; set; }
[Display(Name = "New arrival", GroupName = SystemTabNames.Content, Order = 55)]
public virtual bool NewArrival { get; set; }
[Display(Name = "Best seller", GroupName = SystemTabNames.Content, Order = 58)]
public virtual bool BestSeller { get; set; }
Чтобы найти товары, продающиеся по сниженным ценам, и/или новые поступления, вы можете:
Используйте оператор И/ИЛИ в FilterExpression:
query = query.Filter(x => x.OnSale.Match(true) & x.NewArrival.Match(true));
query = query.Filter(x => x.OnSale.Match(true) | x.NewArrival.Match(true));
Используйте фильтр И/ИЛИ:
var andFilter = new AndFilter();
andFilter.Filters.Add(new TermFilter(searchClient.GetFullFieldName("OnSale", typeof(bool)), true));
andFilter.Filters.Add(new TermFilter(searchClient.GetFullFieldName("NewArrival", typeof(bool)), true));
query = query.Filter(andFilter);
var orFilter = new OrFilter();
orFilter.Filters.Add(new TermFilter(searchClient.GetFullFieldName("OnSale", typeof(bool)), true));
orFilter.Filters.Add(new TermFilter(searchClient.GetFullFieldName("NewArrival", typeof(bool)), true));
query = query.Filter(orFilter);
Обратите внимание, что имя поля, понимаемое Elasticsearch, не совпадает с именем поля в модели типа контента Optimizely. Используйте следующий метод для получения имени индексированного поля:
public static string GetFullFieldName(this IClient searchClient, string fieldName, Type type)
{
if (type != null)
return fieldName + searchClient.Conventions.FieldNameConvention.GetFieldName(Expression.Variable(type, fieldName));
return fieldName;
}
За и против:
- Использование оператора И/ИЛИ: Короткий и простой в использовании, но не подходит для динамического построения фильтров.
- Использование фильтра И/ИЛИ: Более длинный код, но позволяющий гибко строить фильтры на основе имен полей и входных значений.
Как сортировать результаты поиска на основе набора условий
Поиск и навигация позволяют сортировать по одному или нескольким полям:
query = query.OrderBy(x => x.Name).ThenByDescending(x => x.StartPublish);
Пример требования: Размещайте в верхней части страницы товары-бестселлеры, за ними следуют новинки, а затем товары со скидками.
Добиться этого можно с помощью усиления соответствия:
query = query.BoostMatching(x => (x as GenericProduct).NewArrival.Match(true), 2);
query = query.BoostMatching(x => (x as GenericProduct).OnSale.Match(true), 3);
query = query.BoostMatching(x => (x as GenericProduct).BestSeller.Match(true), 4);
Проблема: Если продукт продается и является новым, он отображается наверху, даже если он не является бестселлером. Оценка этого продукта (5) выше, чем у бестселлера (4).
Решение: Убедитесь, что бестселлеры всегда находятся наверху, установив значение Boost по следующему правилу: Следующее значение Boost = сумма всех предыдущих значений Boost + 1:
query = query.BoostMatching(x => (x as GenericProduct).NewArrival.Match(true), 2);
query = query.BoostMatching(x => (x as GenericProduct).OnSale.Match(true), 3);
query = query.BoostMatching(x => (x as GenericProduct).BestSeller.Match(true), 6);
Заключение
Эти советы основаны на моем опыте работы с поиском и навигацией. Надеюсь, они помогут вам реализовать аналогичные функции.
Приятного вам программирования!
01 июля 2024 г.