Модуль Faceted Search — поиск с помощью "уточнений". PINQ - Опрашиваемые наборы данных

Содержание статей:
Предыдущая статья:

Фасеты - это определенные ограничения на тип значений XDTO. Один фасет определяет тип ограничения и значение ограничения. Например [Максимум включающий - 5]. Тип значения XDTO может хранить в себе несколько фасетов, но их типы должны быть уникальны, то есть нельзя указать два фасета [Максимум включающий - 5] и [Максимум включающий - 3].

В данной статье хочу показать как можно при помощи фасетов сделать проверку входных и как сделать параметр ws-операции составного типа.

Поставим простую задачу - сделать выгрузку номенклатуры через веб-сервис. Будем выгружать код, наименование, цену и остаток в магазине. Но справочник может быть очень большим, потому при вызове ws-операции должна быть возможность установить отбор. Будем отбирать по коду номенклатуры.

Создадим новую базу и добавим новый пакет XDTO, назовем его ПакетXDTO, укажем пространство имен.

Далее добавим в пакет Тип значения как показано на рисунке.


Давайте создадим тип "Код" для организации отбора по уникальному идентификатору номенклатуры. Соответственно, новый тип "Код" можно получить из типа string, добавив ограничение на количество символов. Символов должно быть 9, то есть количество символов в коде номенклатуры. Для фасета "Пробельные символы" установим значение "collapse", это позволит вывести ошибку, если в коде имеются пробелы.


Теперь таким же образом создадим ТипЗначения "Цена". Для него установим минимум 0, максимум 1 000 000.


Для решения задачи создадим справочник номенклатуры, остатки будем хранить в одном из его реквизитов - это не принципиально.


Ну, теперь приступим к созданию веб-сервиса. Назовем его "Остатки" и добавим 3 параметра:
  • Код - тип Код, который мы ранее создали. По данному параметру будем устанавливать отбор на код номенклатуры;
  • ЦенаОт - тип Цена. Это нижняя граница цены товара;
  • ЦенаДо - тип Цена. Это верхняя граница цены товара.

Для того что бы веб сервис вывел массив товаров, у каждого из которых есть код, наименование, цена и остаток создадим ОбъектXDTO "Номенклатура", в котором укажем поля:

  • Код - тип Код;
  • Наименование - тип string;
  • Цена - тип Цена;
  • Остаток - тип int

И создадим ОбъектXDTO "Товары", который будет иметь одно свойство "Номенклатура", но с возможностью вывода списком. В качестве типа поля "Номенклатура" объекта "Товары" укажите объект "Номенклатура". Подробнее о том как передать массив через веб-сервис можно прочитать .

Перейдем к свойствам операции "Остатки". Укажем тип возвращаемого значения - "Товары" и откроем ее модуль. Напишем такой код:

Функция Остатки (Код , ЦенаОт , ЦенаДо )

Запрос = Новый Запрос;
Запрос . Текст =
"ВЫБРАТЬ
|Номенклатура.Код,
|Номенклатура.Наименование,
|Номенклатура.Цена,
|Номенклатура.Остаток
|ИЗ
|Справочник.Номенклатура КАК Номенклатура
|ГДЕ
|1 = 1
|И 2 = 2" ;

Если ЗначениеЗаполнено (Код )
И Код <> " 000000000 " Тогда
Запрос . Текст = СтрЗаменить (Запрос . Текст , " 1 = 1 " , " Номенклатура.Код = &Код " );
Запрос . УстановитьПараметр (" Код " , Код );
КонецЕсли;

Если НЕ ЦенаОт = ЦенаДо Тогда
Запрос . Текст = СтрЗаменить (Запрос . Текст , "2 = 2" , "Номенклатура.Цена МЕЖДУ &ЦенаОт И &ЦенаДо" );
Запрос . УстановитьПараметр ("ЦенаДо" , ЦенаДо );
Запрос . УстановитьПараметр ("ЦенаОт" , ЦенаОт );
КонецЕсли;

РезультатЗапроса = Запрос . Выполнить ();

ВыборкаДетальныеЗаписи = РезультатЗапроса . Выбрать ();
ТипXDTOТовары = ФабрикаXDTO . Тип (, "Товары" );

Товары = ФабрикаXDTO . Создать (ТипXDTOТовары );
ТипXDTOНоменклатура = ФабрикаXDTO . Тип ("http://codenotes-1c.blogspot.ru/" , "Номенклатура" );
Пока ВыборкаДетальныеЗаписи . Следующий () Цикл
Номенклатура = ФабрикаXDTO . Создать (ТипXDTOНоменклатура );
Номенклатура . Код = ВыборкаДетальныеЗаписи . Код ;
Номенклатура . Наименование = ВыборкаДетальныеЗаписи . Наименование ;
Номенклатура . Цена = ВыборкаДетальныеЗаписи . Цена ;
Номенклатура . Остаток = ВыборкаДетальныеЗаписи . Остаток ;
Товары . Номенклатура . Добавить (Номенклатура );
КонецЦикла ;

Возврат Товары ;

КонецФункции

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

  • без параметров. Если быть точным то укажем код "000000000", цену от =0, цену до = 0. Потому что, пустые параметры недопустимы.

Ну и у параметра "Код" ws-операции "Остатки" укажем этот тип. После чего мы сможем указывать код номенклатуры как в виде числа, так и в виде строки. Без переделки кода можем указать только 0, что соответствует пустому значению параметра, и отбор не будет установлен.

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

Далее, в качестве справки приведу значение каждого поля свойства. Данное описание взято по ссылке: К чему относится понятие «Фасет» в рамках модели XDTO? Что такое фасет? Авторам большое спасибо!

  • Базовый тип - тип, который используется как основа. По умолчанию anyType. От этого значения зависит допустимый набор фасетов.
  • Длина — фасет длины. Содержит количество единиц длины, причем единица длины имеет различный смысл для различных типов. Для типов «string» и «anyURI» длина содержит количество символов. Для типов «hexBinary» и «base64Binary» длина содержит количество байт двоичных данных. Для типов, определяемых списком, длина содержит количество элементов списка;
  • МаксВключающее — фасет максимума, включающего границу. Ограничивает пространство значений данного типа максимальным значением. Любое значение данного типа меньше либо равно указанному значению;
  • МаксДлина — фасет максимальной длины. Содержит максимальное количество единиц длины, причем единица длины имеет различный смысл для различных типов. Для типа «string» максимальная длина содержит максимальное количество символов. Для типов «hexBinary» и «base64Binary» максимальная длина содержит максимальное количество байт двоичных данных. Для типов, определяемых списком, максимальная длина содержит максимальное количество элементов списка;
  • МаксИсключающее — фасет максимума, не включающего границу. Ограничивает пространство значений данного типа максимальным значением. Любое значение данного типа меньше указанного значения;
  • МинВключающее — фасет минимума, включающего границу. Ограничивает пространство значений данного типа минимальным значением. Любое значение данного типа больше либо равно указанному значению;
  • МинДлина — фасет минимальной длины. Содержит минимальное количество единиц длины, причем единица длины имеет различный смысл для различных типов. Для типа «string» минимальная длина содержит минимальное количество символов. Для типов «hexBinary» и «base64Binary» минимальная длина содержит минимальное количество байт двоичных данных. Для типов, определяемых списком, минимальная длина содержит минимальное количество элементов списка;
  • МинИсключающее — фасет минимума, не включающего границу. Ограничивает пространство значений данного типа минимальным значением. Любое значение данного типа больше указанного значения;
  • Перечисление — фасет перечисления. Определяет набор допустимых значений данного типа;
  • ПробельныеСимволы — фасет пробельных символов. Может принимать одно из трех значений:
    • Сохранять — строка может содержать любые пробельные символы;
    • Заменять — строка не должна содержать #x9 (табуляция), #xA (перевод строки) и #xD (возврат каретки). Если они существуют, то они должны быть заменены символом #x20 (пробел);
    • Сворачивать — дополнительно к требованиям, указанным для значения replace, строка не должна содержать парных символов #x20 (пробел), а также лидирующих и завершающих символов #x20 (пробел);
  • ЦифрВсего — фасет общего количества цифр. Содержит общее количество разрядов числа (целая часть плюс дробная часть);
  • ЦифрДробнойЧасти — фасет количества цифр дробной части. Содержит количество разрядов дробной части числа.

Организует на сайте так называемый фасетный поиск (фасетную навигацию). Смысл его в том, что результаты поиска можно уточнять с помощью различных характеристик материала - автор, тип, термин, дата создания и т.п.

Например если у вас интернет магазин по продаже электронной технике, и пользователь вводит в поиск фразу аудио плеер . На странице с результатами, помимо самих результатов, будут присутствовать фасеты:

- Раздел : аудиотехника (54), компьютерная техника (85)
- Брэнд : Apple (25), Samsung (68), iRiver (78)
- Наличие на складе : есть (456), нет (12)
- Цена : 100-1000$ (45), 1000-10000$ (12)

и т.д. В скобках будет указано число товаров (нод), которые соответствуют этим характеристикам. Кликая по ссылкам, пользователь будет сужать результаты поиска.


С одной стороны это альтернатива раскрытым фильтрам в Views, с другой альтернатива стандартному расширенному поиску.

Установка

Раздел Facets

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

Раздел Results page

Display style - стиль вывода результатов поиска: Extracts значит выводить как при обычном поиске (подсвеченный текст, автор, дата); Teasers значит выводить тизеры материалов с помощью соответствующего node.tpl.php.

Use the Extracts display style selectively - Если опция отмечена, то стиль Extracts будет применяться всегда, если введено ключевое слово. Если не отмечать эту опцию то можно использовать модуль в качестве замены навигации по терминам таксономии.

Раздел Current search

Позволяет включить блок Текущий поиск , в котором отображаются условия поиска:

Facet API Bonus для Drupal 7 - это коллекция дополнительных Facet API плагинов и функциональных возможностей, прежде всего фильтра и плагинов зависимостей - и место для хранения большинства дополнительных расширений Facet API.

В настоящее время Facet API Bonus включает в себя:

Facet Dependency (Facet-ные Зависимости) : плагин зависимостей, чтобы сделать один фасет (например "категория продукта"), чтобы показать в зависимости от других фасетов или специфических фасетных активных пунктов (item-ов) (например, "тип содержимого" - это "продукт" или "сервис"). Очень гибкий, поддерживает мультифасеты, для зависимостей, а также регулярное выражение для определения зависимостей фасетного пункта (item-а) , так же как и параметр, как себя вести, если зависимость теряется.

"Exclude Items (Исключить позиции/айтемы)": Плагин для фильтра, для исключения определенных фасетных айтемов по их разметке / названию или внутреннему значению (например, за исключением "page-ей" с "типов содержимого»). Также возможны регулярные выражения.

(Продолжение следует...)

Как показать фасетный поиск на нефасетных страницах

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

Чтобы все это сделать, есть блочный дисплей Views Facets, предусмотренный подмодулем search_api_facetapi

С его помощью можно легко использовать фасетные ссылки для любого поиска на любой желаемой Вами странице. С этой целью есть две опции:

Показать фасеты непосредственно в блоке вьюса

Необходимо или создать новый вьюс на основе поискового индекса, который вы хотите использовать, или изменить старый вьюс. Добавьте тип отображения "Facets block" (Фасетный блок) для просмотра и настройки "Facet field" (фасетного поля) и "Search page path" (Пути страницы поиска) в "Настройке блока".

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

Настройте любые (контекстные) фильтры, которые нужно применить к результату, который используется для фасетных ссылок (например, учитывать только категории для опубликованных нод определенного типа контента). Exposed фильтры игнорируются. Настройки формата и полей игнорируются, но вы также можете изменить настройки нажав на "Прочее".

Список фасетных ссылок будет выведен на страницах, которые были указаны.

Однако существуют некоторые ограничения в этом варианте:

Фасетные ссылки всегда будет оформлены в виде списка, невозможно будет переписать или отформатировать выбранное.
В частности, также невозможно использовать обычные Facet API виджеты для этих фасетов. Это потому, что достаточно сложно добиться повторного использования Facet API компонентов снаружи Facet API .
Если вы хотите отобразить фасеты для более чем одного поля, вы должны добавить дополнительные _вюсовые диспели для фасетного блока и каждый будет выполнять отдельный поисковый запрос при отображении.

Чтобы разрешить эти недостатки, существует второй вариант:

Вы также можете просто использовать дисплей фасетного блока, чтобы выполнить поиск, а затем использовать обычное Facet API для фасетных блоков чтобы вывести в них фасеты. Чтобы сделать это, создайте дисплей фасетного блока, как и раньше, но установите настройку "Скрыть блок" в настройках блока. Таким образом, на страницах, на которых появится блок, поисковый запрос выполняется, но блок будет скрыт.

Теперь вы можете создать фасетные блоки для этого поиска как обычно, на индексной станице на вкладке "Фасеты". Вы просто должны убедиться в том, что фасет активен для дисплея фасетного блока (обычно ID будет равен search_api_views: -facets_block) в "Display for searches" / "Search IDs . Затем, все обычные опции Facet API могут быть использованы для определения вида и поведения отображаемых фасетных блоков. Фасеты в этих блоках будут автоматически использовать путь, выданный во вьюсовых фасетных блоках в настройках "Путей поисковой страницы".

Тем не менее, есть также некоторые проблемы с этим подходом: Во-первых, в настоящее время не представляется возможным вывести тот же фасет в двух разных местах (# 1411160: Разрешить фасетуотображаться несколько раз в той же сфере). Таким образом, список фасетов на главной странице должен быть в той же области и месте, для поиска и быть отстилизирован так же. Обход этого по любому (или путем клонирования фасетного блока, или путем альтера (изменения) дисплея для перемещения блока) в настоящее время по-прежнему требуется кодинг (если вы не используете панели (или что-то аналогичное) для отображения блоков).

Вторая проблема - это то же самое, что описано в Часто задаваемых вопросах (Search API FAQs) - для того, чтобы фасетные блоки работали, вы должны убедиться, что вьюс выполняется перед тем, как блоками рендерятся. Однако, поскольку вы можете положить вьюсовый блок в любом регионе, (поскольку он любом случае не будет отображаться), это не должно быть слишком большой проблемой, чтобы найти положение, при котором это требование считается выполненным.

Добавление фасетного блока в панель

Почему все, что выше описано про фасеты, фасетный поиск и про фасетные блоки может не работать?

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

Показать последний уровень иерархической таксономии в мультифасетах

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

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

Xитать полезную информацию про все это вот тут

Переводы сделаны на основе следубщих страниц.

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

Но сначала 15 секунд политинформации (сам себя не похвалишь, никто не похвалит). В этом году Sphinx прошел во в номинациях SysAdmins и Enterprise (говорят, в номинации Developers не добрали совсем чуть-чуть). Голосование продлится еще неделю (до 20го числа). Кроме рабочего email адреса, ничего не нужно. Заранее спасибо всем, кто не даст нам пропасть!

И обратно к разработке. Что вообще такое мульти-запросы, и откуда берется обещанное втрое быстрее?

Мульти-запросы (multi-queries) - это механизм, который позволяет отослать несколько поисковых запросов одним пакетом.

Методы API, реализующие механизм мульти-запросов, называются AddQuery() и RunQueries() . (Кстати, «обычный» метод Query() внутри использует их же: один раз вызывает AddQuery(), и затем сразу RunQueries()). Метод AddQuery() сохраняет текущее состояние всех настроек запроса, выставленных предыдущими API вызовами, и запоминает запрос. Настройки уже запомненного запроса более меняться не будут, любый вызовы API их не тронут, соотв-но для последующих запросов можно использовать любые другие настройки (другой режим сортировки, другие фильтры, итп). Метод RunQueries() фактически отсылает все запомненные запросы одним пакетом и возвращает несколько результатов. На участвующие в пакете запросы никаких ограничений не накладывается. Количество запросов на всякий случай ограничено директивой max_batch_queries (добавлена в 0.9.10, ранее фиксированным числом 32), но это в общем-то только проверка против битых пакетов.

Зачем использовать мульти-запросы? Вообще говоря, все сводится к производительности. Во-1х, отсылая запросы к searchd одним пакетом, всегда экономим немножко ресурсов и времени на том, что отсылаем туда-сюда меньше сетевых пакетов. Во-2х, что значительно более важно, searchd получает возможность провести некоторые оптимизации над всем пакетом запросов. Со временем постепенно добавляются новые оптимизации, поэтому имеет смысл всегда, когда можно, отсылать запросы пакетами - тогда при обновлении Sphinx новые пакетные оптимизации включатся полностью автоматически. В случае, когда никаких пакетных оптимизаций применить нельзя, запросы просто будут обработаны по одному, без каких-либо видимых отличий для приложения.

Зачем (точнее когда) мульти-запросы НЕ использовать? Все запросы в пакете должны быть независимы, но иногда это не так, и запрос Б может зависеть от результатов запроса А. Например, можем хотеть показывать результаты поиска из дополнительного индекса только тогда, когда в главном индексе ничего не нашлось. Или просто выбирать разное смещение во 2й набор результатов в зависимости от количества совпадений в 1м наборе. В таких случаях придется использовать отдельные запросы (или отдельные пакеты).

Есть две важные пакетные оптимизации, про которые стоит знать: оптимизация общих запросов (доступна начиная с версии 0.9.8), и оптимизация общих поддеревьев (доступн начиная с находящейся в разработке версии 0.9.10).

Оптимизация общих запросов работает так. searchd выбирает из пакета все запросы, у которых отличаются только настройки сортировки и группровки, а полнотекстовая часть, фильтры итп совпадают - и проводит поиск только один раз. Например, если в пакете 3 запроса, текстовая часть у всех «ipod nano», но 1й запрос выбирает 10 самых дешевых результатов, 2й группирует результаты по ID магазина и сортирует магазины по рейтингу, а 3й запрос просто выбирает максимальную цену, поиск «ipod nano» отработает только один раз, но из его результатов будут построены 3 по-разному отсортированных и сгруппированных отклика.

Так называемый фасеточный поиск является частным случаем, для которого применима данная оптимизация. В самом деле, его можно реализовать, запустив несколько поисковых запросов с разными настройками: один для основных результатов поиска, еще несколько с таким же поисковым запросом, но разными настройками группировки (top-3 авторов, top-5 магазинов, итп). Когда все, кроме сортировки и группировки одинаковое, оптимизация включается и скорость неплохо растет (пример ниже).

Оптимизация общих поддеревьев еще более интересная штука. Она позволяет searchd использовать сходства между разными запросами внутри пакета. Внутри всех пришедших отдельных - разных! - полнотекстовых запросов выявляются общие части, и если такие есть, промежуточные результаты расчета кешируются и разделяются между запросами. Например, вот в таком пакете из 3 запросов

Barack obama president barack obama john mccain barack obama speech

Есть общая часть из 2х слов («barack obama»), которую можно для всех трех запросов вычислить ровно один раз и закешировать. Именно этим оптимизация общих поддеревьев и занимается. Максимальный размер кеша на каждую пачку жестко ограничивается директиваи subtree_docs_cache и subtree_hits_cache, так что если общая часть «i am» найдется в ста миллионах документов, память у сервера внезапно таки не кончится.

Вернемся обратно к оптимизации про общие запросы. Вот пример кода, который запускает один и тот же запрос, но с тремя разными режимами сортировки:
sorting modes:

Require ("sphinxapi.php"); $cl = new SphinxClient (); $cl->SetMatchMode (SPH_MATCH_EXTENDED2); $cl->SetSortMode (SPH_SORT_RELEVANCE); $cl->AddQuery ("the", "lj"); $cl->SetSortMode (SPH_SORT_EXTENDED, "published desc"); $cl->AddQuery ("the", "lj"); $cl->SetSortMode (SPH_SORT_EXTENDED, "published asc"); $cl->AddQuery ("the", "lj"); $res = $cl->RunQueries();

Как узнать, сработала ли оптимизация? Если сработала, в соответствующих строчках лога будет поле с «мультипликатором», который показывает, сколько запросов было обработано вместе:

0.040 sec x3 the 0.040 sec x3 the 0.040 sec x3 the

Обратите внимание на «x3», это именно оно - означает, что запрос был оптимизирован и обработан в числе пакета из 3 запросов (включая этот). Для сравнения, вот так выглядит лог, в котором те же самые запросы были отправлены по одному:

0.059 sec the 0.091 sec the 0.092 sec the

Видно, что время поиск на каждый запрос в случае с мульти-запроса улучшилось от 1.5 до 2.3 раз, в зависимости от режима сортировки. На самом деле, это не предел. Для обоих оптимизаций известны случаи, когда скорость улучшалась в 3 и более раз - причем не на синтетических тестах, а вполне себе в продакшне. Оптимизация общих запросов довольно хорошо ложится на вертикальные поиски по товарам и онлайн магазины, кеш общих поддеревьев соовт-но на data mining запросов; но, разумеется, строго этими областями применимость не ограничивается. Например, можно делать поиск вообще без полнотекстовой части и считать несколько разных отчетов (с разной сортировкой, группировкой итп) по одинаковым данных за один запрос.

Каких еще оптимизаций можно ожидать в будущем? Зависит от вас. Пока что в долгосрочном плане записана понятная оптимизация про одинаковые запросы с разными наборами фильтров. Знаете другой частый паттерн, котороый можно ловко соптимизировать? Присылайте!

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

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

Лучше всего продемонстрировать принцип фасетной навигации на конкретном примере.

Например, вы собираетесь купить мобильный телефон в интернет-магазине. Вы хотите найти телефон определенной модели, цвета, цены, марки. Было бы удобнее и быстрее найти то, что вам нужно, сузив поиск, используя несколько или все параметры (фасеты).

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

Рассмотрим основные затруднительные вопросы.

1. Как много фасетов необходимо, чтобы ваш сайт был качественно проиндексирован?

В идеале, «глубина» фасета не должна превышать 100 наименований. Это позволит поисковым роботам проиндексировать все страницы ресурса. Большинство специалистов по продвижению сайтов склонны полагать, что поисковые роботы могут распознать более 100 ссылок на одной странице.

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

2. Фасеты и поисковые фильтры

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

3. Сортировка

Возможно, вы захотите включить дополнительные параметры выбора (например, цена товара, его популярность и т. д.). Конечно, для клиентов это очень удобно, но при этом существует риск возникновения дублированного контента. Если вы не хотите, чтобы одна и та же страница была индексирована поисковым роботом несколько раз из-за наличия различных навигационных путей ее нахождения, воспользуйтесь JavaScript или Ajax.

4. Проблема дублированного контента

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

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

И еще раз об уникальности контента…

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

Итак, вот что следует запомнить:

  1. создавайте так много фасетов, сколько необходимо для размещения на одной странице не более 100 товаров;
  2. убедитесь, что для каждой ключевой фразы, по которой вы хотите ранжироваться в поисковых системах, существует своя целевая страница;
  3. неправильная сортировка может приводить к появлению дублированного контента, чтобы этого избежать используйте Ajax и Java Script для закрытия некоторых внутренних страниц от индексации;
  4. не важно, каким навигационным путем пользователь находит ту или иную страницу, индексироваться должна только одна страница;
  5. не забывайте: информационное наполнение должно быть интереснее и привлекательнее.