На чем лучше реализовать фасетный поиск. Как построить фасетный поиск с помощью счетчиков фасетов? Мы каждый раз выбираем данные из MySQL

{ "query": { "and": [ { "terms": {"country": ["be", "fr"]} }, { "terms": {"category": ["books", "movies"]} } ] } }

Для счетчиков мы можем использовать встроенные агрегаты из Elasticsearch. Каждый из двух фасетов хранится как одно поле в индексе, поэтому мы можем использовать агрегирование терминов в каждом из этих полей. Агрегация вернет счетчик за значение этого поля.

{ "query": { "and": [ { "terms": {"country": ["be", "fr"]} }, { "terms": {"category": ["books", "movies"]} } ] }, "aggregations": { "countries": { "terms": {"field": "country"} }, "categories": { "terms": {"field": "category"} } } }

Если бы вы выполнили этот запрос, вы заметите, что счетчики отключены. В двух не отобранных странах, в Португалии и Бразилии, есть счетчик 0. Хотя есть фактические результаты, если мы хотим их выбрать (из-за ORвнутренней грани). Это происходит потому, что по умолчанию Elasticsearch выполняет свои агрегирования в результирующем наборе. Это означает, что если вы выберете Францию, фильтры другой страны будут иметь счет 0, потому что в результирующем наборе содержатся только элементы из Франции.

Чтобы исправить это, нам нужно дать команду Elasticsearch выполнить агрегацию во всем наборе данных, игнорируя запрос. Мы можем сделать это, определив наши скопления как глобальные.

{ "query": { "and": [ { "terms": {"country": ["be", "fr"]} }, { "terms": {"category": ["books", "movies"]} } ] }, "aggregations": { "all_products": { "global": {}, "aggregations": { "countries": { "terms": {"field": "country"} }, "categories": { "terms": {"field": "category"} } } } } }

Если бы мы просто сделали это, наши счетчики всегда были бы одинаковыми, потому что они всегда будут рассчитывать на весь набор данных, независимо от наших фильтров. Наши агрегаты должны стать немного более сложными, чтобы это работало, нам нужно добавить к ним фильтры. Каждое агрегирование должно рассчитывать на набор данных со всеми применяемыми фильтрами, за исключением собственных. Таким образом, агрегация за счет во Франции рассчитывает на набор данных с применением фильтра категории, но не фильтр стран:

{ "query": { "and": [ { "terms": {"country": ["be", "fr"]} }, { "terms": {"category": ["books", "movies"]} } ] }, "aggregations": { "all_products": { "global": {}, "aggregations": { "countries": { "filter": { "and": [ { "terms": {"category": ["books","movies"]} } ] }, "aggregations": { "filtered_countries": { "terms": {"field": "country"} } } }, "categories": { "filter": { "and": [ { "terms": {"country": ["be","fr"]} } ] }, "aggregations": { "filtered_categories": { "terms": {"field": "category"} } } } } } } }

{ "took": 153, "timed_out": false, "_shards": { "total": 5, "successful": 5, "failed": 0 }, "hits": { "total": 3, "max_score": 0, "hits": ["..."] }, "aggregations": { "all_products": { "doc_count": 21, "filterted categories": { "doc_count": 13, "categories": { "doc_count_error_upper_bound": 0, "sum_other_doc_count": 0, "buckets": [ { "key": "movies", "doc_count": 6 }, { "key": "music", "doc_count": 4 }, { "key": "books", "doc_count": 3 } ] } }, "filtered_countries": { "doc_count": 15, "countries": { "doc_count_error_upper_bound": 0, "sum_other_doc_count": 0, "buckets": [ { "key": "fr", "doc_count": 6 }, { "key": "br", "doc_count": 4 }, { "key": "be", "doc_count": 3 }, { "key": "pt", "doc_count": 2 } ] } } } } }

Yii2 framework $terms = QueryHelper:: terms ("categories.name" , "my category" ) ; $nested = QueryHelper:: nested ("string_facet" , QueryHelper:: filter ([ QueryHelper:: term ("string_facet.facet_name" , [ "value" => $id , "boost" => 1 ] ) , QueryHelper:: term ("string_facet.facet_value" , [ "value" => $value , "boost" => 1 ] ) , ] ) ) ; $filter = QueryHelper:: should ($nested ) ;

В сегодняшнем уроке мы с вами попробуем воссоздать имитацию фасетного (фасеточного) поиска средствами Javascript. Я подразумеваю, что вы уже знаете что такое фасетный поиск, раз читаете данный туториал, в противном случае погуглите или загляните на Amazon или мою Демку .

Для начала нам понадобится библиотека github.com/eikes/facetedsearch. Скачайте её и подключите файл facetedsearch.js к нашему проекту. Так же нам понадобятся библиотеки jQuery и Underscore.

Дисклеймер: Я понимаю, что JQ уже давно не торт, но использую его как привычный синтаксический сахар, вы можете перепилить это под более привычные вам библиоетки или на ванильном JS.

Итак для начала сделаем простенькую разметку с подключенными зависимостями:

Document // Сюда мы выведем фасетные фильтры // А тут будут наши элементы

Теперь нам нужно описать настройки нашего приложения и создать шаблон вывода элементов массива которые мы будем сортировать при помощи фасетов:

$(function(){ var item_template = // Описывем шаблон "" + "" class="img-responsive">" + ", " + "

" + "" + ", " + ", " + "

" + "

" + ""; settings = { items: example_items, facets: { // Указывем категории фасетов "category" : "What Category", "continent" : "Which Continent", "language" : "Programming Language" }, resultSelector: "#results", // DOM элемент куда мы выводим результаты facetSelector: "#facets", // DOM элемент для фасетов resultTemplate: item_template, paginationCount: 8, // Колличество элементов на страницу orderByOptions: {"firstname": "First name", "lastname": "Last name", "category": "Category", "RANDOM": "Random"}, facetSortOption: {"continent": ["North America", "South America"]} } $.facetelize(settings); });

Ну и собственно создать сам JSON массив с элементами для отображения в нашем фасетном поиске на JS:

Var items = [ { "firstname": "Mary", "lastname": "Smith", "imageURL": "http://lorempixel.com/150/150/cats/2", "description": "Sed Ea Amet. Stet Voluptua. Nonumy Magna Takimata ", "category": "Mouse", "language": ["Smalltalk", "XSLT"], "continent": "Africa" }, { "firstname": "Patricia", "lastname": "Johnson", "imageURL": "http://lorempixel.com/150/150/cats/3", "description": "Ut Takimata Sit Aliquyam Labore Aliquyam Sit Sit Lorem Amet. Ipsum Rebum. ", "category": "Lion", "continent": "North America" }, ... ];

Данный массив я бы вынес в отдельный JS файл который бы формировался динамически, из БД например.

Вот собственно и всё, мы получаем фасетный поиск на JavaScript и можем его кастомизировать. Далее я привожу переведённую документации библиотеки, где вы можете подсмотреть необходимые вам триггеры.

Документация Функции

Две функции экспортируются в пространство имен jQuery.

facetelize Используется для инициализации фасетного поиска с заданными настройками.

facetUpdate Может использоваться, если вы хотите изменить состояние фасетного поиска извне.

Настройки объектов

items: Массив элементов, которые будут отфильтрованы и отсортированы в процессе.

facets: Объект, для которого ключи соответствуют ключам элементов и значениям, является заголовком для этого фасета. Элементы будут отфильтрованы на основе того, какое значение они имеют для этих ключей.

orderByOptions: Подобно фасетам, за исключением того, что эти пары «ключ-значение» используются только для сортировки. Когда ключ RANDOM включен, результаты могут быть рандомизированы.

facetSelector: Это селектор, который используется для поиска DOM-узла, из которого выбираются фильтры фасетов.

resultSelector: Это селектор, который используется для поиска DOM-узла, где отображаются результаты.

resultTemplate: Строка, которая используется Underscore шаблонизатором Для рендеринга каждого элемента из массива items . Следующие атрибуты добавляются к каждому элементу, который также можно использовать в шаблоне: batchItemNr , batchItemCount и totalItemCount .

state: Этот объект сохраняет текущие фильтры, сортирует: currentResult и прочие. Вы можете предоставить строку orderBy или объект filters для их предварительной настройки.

enablePagination: Boolean для включения пагиналора и кнопи "load more", по умолчанию true .

paginationCount: Если включен пагинатор, задаёт количество элементов на страницу, по умолчанию - 50.

facetSortOption: Используйте эту функцию, чтобы изменить порядок элементов фасетов. Принимает объект, в котором ключи соответствуют именам фасетов и значениям в массив значений фасетов, которые могут быть расположены в том порядке, в котором вы хотели бы их видеть. В этом примере будут отсортированы континенты в другом порядке, элементы, не включенные в массив, будут добавлены в алфавитном порядке:

FacetSortOption: {"continent": ["North America", "South America"]}

Есть еще несколько шаблонов, пожалуйста, посмотрите исходный код facetedsearch.js , чтобы увидеть все доступные параметры шаблона.

События

Вы можете привязываться к некоторым событиям, которые должны отправить уведомления, когда произошли некоторые действия. Для этого используем систему событий jquery:

facetuicreated: Вы можете привязать эту функцию к DOM элементу settings.facetSelector который должен быть уведомлен, когда пользовательский интерфейс был создан.

facetedsearchresultupdate: Вы можете привязать эту функцию к DOM элементу settings.resultSelector что бы получить уведомление о результатах обновления.

facetedsearchfacetclick: Это событие вызывается при щелчке фасета и его срабатывании на settings.facetSelector элементе. Который получает идентификатор фасета как аргумент.

facetedsearchorderby: Это событие вызывается при щелчке элемента сортировки по элементу settings.facetSelector. Он получает ID order в качестве аргумента.

$(settings.resultSelector).bind("facetedsearchresultupdate", function(){ // do something, maybe });

Современный человек старается тратить на покупки все меньше времени. Медленные каталоги товаров отталкивают покупателей, магазин теряет клиентов и часть прибыли. Сделайте свой интернет-магазин привлекательнее вместе с технологией фасетного Фасетный - т.е. предопределенный. поиска. Создайте фасетные индексы и значительно ускорьте поиск товаров и работу всего каталога.

Примечание: Механизм фасетного поиска доступен с версии 15.0.1 модуля Информационные блоки и интегрирован с компонентом Компонент - это программный код, оформленный в визуальную оболочку, выполняющий определённую функцию какого-либо модуля по выводу данных в Публичной части. Мы можем вставлять этот блок кода на страницы сайта без непосредственного написания кода. Умный фильтр Компонент подготавливает фильтр для выборки из инфоблока и выводит форму фильтра для фильтрации элементов. Компонент должен подключаться перед компонентом вывода элементов каталога, иначе список элементов фильтроваться не будет. Компонент стандартный, входит в дистрибутив модуля и содержит три шаблона: .default , visual_horizontal и visual_vertical . (Последние два шаблона не поддерживаются, остались для сохранения совместимости.)

В визуальном редакторе компонент расположен по пути Контент > Каталог > Умный фильтр .

Компонент относится к модулю Информационные блоки.

Подробнее о фасетном поиске

Рассмотрим на примере:

Мы заходим в интернет-магазин и в фильтре выбираем, что нам нужна футболка красного цвета:

  • Без фасетного поиска фильтр начал бы перебирать весь список товаров на соответствие товару «Футболка» со свойством цвет «Красный», что заняло бы немало времени при большом количестве товара;
  • Если настроить фасетный поиск, то создаются готовые поисковые наборы товаров по некоторому значению свойства (фасетные индексы ), т.е. варианты возможных запросов Например красная футболка, все товары черного цвета из хлопка, платья размера XS и т.д. в умном фильтре просчитаны заранее и результат выдается сразу. Такой поиск товаров работает намного быстрее.

Создадим фасетные индексы за несколько простых действий:

Нужно ли пересоздавать фасетные индексы?

Фасетные индексы пересоздаются автоматически или требуется пересоздать их вручную в зависимости от произведенных действий:

Автоматически Добавили новые или отредактировали существующие товары .
не создают новых свойств.
Вручную Система подскажет вам об этом с помощью сообщения вверху страниц
административного раздела.
Добавили новые или отредактировали разделы каталога .
При добавлении нового или удалении свойства из умного фильтра .
При выгрузке товаров, например, из 1С, если товары создают новые свойства.

Фасетный поиск улучшает работу каталога товаров. Для его использования необходимо:

  • Создать фасетные индексы для каталога с товарами;
  • Следить за оповещением о необходимости пересоздания индексов вручную.
  • Фасетная навигация – это проблема всех e-commerce сайтов. Чрезмерное количество страниц, которые используются для разных вариантов одного и того же элемента, создает угрозу эффективности поиска. Это может негативно повлиять на SEO и пользовательский опыт. Что такое фасетная навигация, и как ее улучшить, рассказали специалисты из блога SEO Hacker.

    Фасетная навигация: определение

    Этот тип навигации встречается, как правило, в боковых панелях сайтов электронной коммерции, содержит фильтры и фасеты – параметры, которые пользователь настраивает по своему желанию. позволяет клиентам интернет-магазинов искать желаемый товар с помощью комбинации атрибутов, которые будут фильтровать продукты, пока пользователи не найдут то, что им нужно.

    Фасеты и фильтры отличаются друг от друга. Вот в чем заключается разница:

    • Фасеты – индексированные категории. Они помогают уточнять списки товаров и действуют как расширение основных категорий. Фасеты добавляют уникальное значение для каждого выбора, который делает пользователь. Так как фасеты индексированы, они должны отправлять релевантные сигналы поисковой системе, гарантируя, что страница содержит все важные атрибуты.

    • Фильтры используются для сортировки и уточнения элементов внутри списков. Они необходимы для пользователей, но не для поисковых систем. Фильтры не индексируются, потому что они не меняют содержимое страницы, а лишь сортируют ее в другом порядке. Это приводит к множественному URL-адресу, имеющему дублированный контент.

    Потенциальные проблемы

    У каждой возможной комбинации фасетов есть собственный уникальный URL-адрес. Он может стать причиной некоторых проблем с точки зрения SEO. Вот основные из них:

    • Дублированный контент.
    • Трата бюджета на сканирование.
    • Устранение разницы в ссылках.

    По мере роста вашего сайта увеличивается и количество дублированных страниц. Входящие ссылки могут поступать на различные дублированные страницы. Это снижает ценность ссылок и ограничивает возможности ранжирования страниц.

    Повышается также вероятность каннибализации ключевых слов. Несколько страниц пытаются ранжировать одни и те же ключевые слова, что приводит к менее стабильному и более низкому ранжированию. Этой проблемы можно было бы избежать, если бы каждое ключевое слово предназначалось только для отдельной страницы.

    Решения для фасетной навигации

    При выборе решения проблемы фасетной навигации учитывайте вашу конечную цель: увеличить количество индексируемых страниц или же уменьшить число страниц, которые вы не хотите индексировать. Вот несколько решений, которые могут быть для вас полезными:

    AJAX

    Если вы применяете AJAX, новый URL-адрес не создается, когда пользователь кликает на фасет или фильтр. Поскольку для каждой возможной комбинации фасетов не будет уникальных URL-адресов, проблема дублирования контента, каннибализации ключевых слов и траты расходов на индексацию потенциально исключается.

    AJAX может быть эффективен только до запуска сайта e-commerce. Для решения проблем уже существующих ресурсов он не используется. Также этот метод требует определенных трат с вашей стороны.

    Тег noindex

    Тег noindex используется для того, чтобы боты исключили определенную страницу из индекса. Таким образом она не будет отображаться в результатах поиска Google. Это позволяет уменьшить количество дублированного контента, отображаемого в индексе и результатах поиска.

    Это не решит проблемы с бюджетом на обход, потому что боты все равно будут посещать вашу страницу. Это также не помогает распределить ценность ссылок.

    Атрибут rel=canonical

    С помощью этого атрибута вы сообщаете Google, что у вас есть одна основная предпочтительная страница для индексирования и ранжирования, а все остальные версии контента с этой страницы – всего лишь дубликаты, которые не нужно индексировать.

    София Ибрагимова

    Контент-маркетолог

    Если на одну и ту же страницу вашего сайта можно попасть по нескольким URL-адресам, поисковые роботы будут расценивать каждый адрес как отдельную страницу. Боты решат, что контент на вашем сайте неуникален, а это отрицательно скажется на ранжировании и снизит ваши позиции в выдаче. Чтобы этого избежать, укажите основную каноническую страницу, вставив в блок HEAD следующую последовательность символов:

    Вы можете использовать канонические страницы, чтобы решить проблему дублирования контента, а привязка акций будет объединена с вашей основной страницей. Но есть вероятность, что боты все равно будут сканировать дублированные страницы, а это пустая трата бюджета на обход.

    Robots.txt

    Закрытие части страниц от индексации позволяет добиться хороших результатов. Это простой, быстрый и надежный способ. Удобнее всего установить настраиваемый параметр для указания всех возможных комбинаций фасетов и фильтров, которые вы хотите заблокировать. Включите его в конец каждого URL-адреса, который хотите скрыть (http://полный адрес страницы/robots.txt) или используйте метатег Robots в области HEAD кода страницы.

    При изменении в URL-адресе необходимо помнить, что роботам требуется 3-4 недели, чтобы заметить эти изменения и среагировать на них.

    Здесь тоже существуют определенные проблемы. Ценность ссылок будет ограничена, а также заблокированный URL может быть проиндексирован из-за наличия внешних ссылок.

    Консоль Google Search

    Это отличный способ временно исправить свои проблемы, пока вы работаете над созданием более совершенной и удобной системы навигации. Вы можете использовать консоль Google Search, чтобы сообщить поисковику, как сканировать ваш сайт.

    • Войдите в учетную запись консоли и выберите раздел «Сканирование» (Crawl):

    • Нажмите на кнопку «Параметры URL» (URL Parameters):

    • Укажите влияние каждого из ваших параметров на страницу и то, как Google должен обрабатывать эти страницы.

    Помните, что этот способ скрывает дублированный контент только от поисковых роботов Google. В Bing и Yahoo станицы по-прежнему будут отображаться.

    Как улучшить фасетную навигацию

    Рассмотрим вкратце все методы, которые позволяют создать правильную фасетную навигацию:

    • Использование AJAX
    • Удаление или скрытие ссылок на категории или страницы фильтров, на которых отсутствует контент.
    • Разрешение индексирования определенных комбинаций фасетов, которые имеют большой объем поиска трафика
    • Установка иерархии сайтов через хлебные крошки в категориях и подкатегориях.
    • Создание канонических (основных) страниц для дублированного контента.
    • Консолидация индексирующих свойств со страниц компонентов на весь ряд с помощью разметки страницы с rel = "next" и rel = "prev" .
    Заключение

    Каждое из упомянутых решений имеет свои преимущества и недостатки. Универсального решения не существует, все зависит от специфики вашего бизнеса и конкретного случая. Оптимизированная фасетная навигация позволит вашему сайту ориентироваться на более широкий набор ключевых слов. Чтобы избежать риска, убедитесь, что навигация не только отвечает требованиям поисковых роботов, но также удобна с точки зрения пользовательского опыта.