Отвечаю:
[spoiler]
С версии модуля поиска 10.0.0 добавилась поддержка произвольных параметров связанных с элементами поискового индекса.
Пока в доке это не отражено. Расскажу на примере.
1. Сначала надо связать набор разделов к которым привязан элемент и поисковый индекс.
<?
// файл /bitrix/php_interface/init.php
// регистрируем обработчик
AddEventHandler("search", "BeforeIndex", Array("MyClass", "BeforeIndexHandler"));
class MyClass
{
// создаем обработчик события "BeforeIndex"
function BeforeIndexHandler($arFields)
{
// элемент инфоблока 180 (не раздел)
if($arFields["MODULE_ID"] == "iblock" && $arFields["PARAM2"] == 180 && substr($arFields["ITEM_ID"], 0, 1) != "S")
{
$arFields["PARAMS"]["iblock_section"] = array();
//Получаем разделы привязки элемента (их может быть несколько)
$rsSections = CIBlockElement::GetElementGroups($arFields["ITEM_ID"], true);
while($arSection = $rsSections->Fetch())
{
//Сохраняем в поисковый индекс
$arFields["PARAMS"]["iblock_section"][] = $arSection["ID"];
}
}
//Всегда возвращаем arFields
return $arFields;
}
}
?> |
Терерь если пересохранить элемент этого инфоблока или выполнить полную переиндексацию, то на странице просмотра содержания таблиц (в модуле производительности /bitrix/admin/perfmon_table.php?lang=ru&set_filter=Y&table_name=b_search_content_param&find_type=SEARCH_CONTENT_ID&find_PARAM_NAME=i
2 Собственно поиск.
Привожу код страницы с компонентом (несущественные параметры компонента я опустил):
<?
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/header.php");
$APPLICATION->SetTitle("Поиск");
global $arSectionFilter;
$arSectionFilter = array("PARAMS" => array("iblock_section" => 6759));
?><?$APPLICATION->IncludeComponent("bitrix:search.page", ".default", array(
...
"FILTER_NAME" => "arSectionFilter",
"arrFILTER" => array(
0 => "iblock_max",
),
"arrFILTER_iblock_max" => array(
0 => "180",
),
...
),
false
);?><?require($_SERVER["DOCUMENT_ROOT"]."/bitrix/footer.php");?>
|
3 Если на первом шаге воспользоваться функцией то можно реализовать и поиск по вложенным разделам.
Оставляю это в качестве упражнения.
Для себя мы сделали: идёт разделение результатов по ИБ, со статикой песня отдельная, но тоже решаемая.
Подумаем обязательно.
Я новичок в битриксе и у меня есть пара вопросов по коду:
if($arFields["MODULE_ID"] == "iblock" && $arFields["PARAM2"] == 180 && substr($arFields["ITEM_ID"], 0, 1) != "S"
180 - это id инфоблока, по которому будет осуществляться поиск?
$arSectionFilter = array("PARAMS" => array("iblock_section" => 6759));
6759 - id раздела инфоблока, по которому будет искать поиск? Т.е. если у меня, например, инфоблок "Товары" содержит разделы "Диски", "Книги", "Сувениры" я могу просто сделать выпадающий список рядом со строкой поиска и передавать get'ом id раздела вместо 6759?
А если у меня разел "Книги" содержит подразделы? Т.е. по факту элементы привязаны к подразделам, но поиск нужен по всему разделу "Книги"?
Я правильно понял, что это мне нужно на первом шаге вот здесь
//Получаем разделы привязки элемента (их может быть несколько) $rsSections = CIBlockElement::GetElementGroups($arFields["ITEM_ID"], true); while($arSection = $rsSections->Fetch()) { //Сохраняем в поисковый индекс $arFields["PARAMS"]["iblock_section"][] = $arSection["ID"]; }Спасибо.
init.php:
=====================
// регистрируем обработчик AddEventHandler("search", "BeforeIndex", Array("MyClass", "BeforeIndexHandler")); class MyClass { // создаем обработчик события "BeforeIndex" function BeforeIndexHandler($arFields) { // элемент инфоблока 2 (не раздел) if($arFields["MODULE_ID"] == "iblock" && $arFields["PARAM2"] == 2 && substr($arFields["ITEM_ID"], 0, 1) != "S") { $arFields["PARAMS"]["iblock_section"] = array(); //Получаем разделы привязки элемента (их может быть несколько) $rsSections = CIBlockElement::GetElementGroups($arFields["ITEM_ID"], true); while($arSection = $rsSections->Fetch()) { $nav = CIBlockSection::GetNavChain(2, $arSection["ID"]); while($nav->ExtractFields("nav_")) { //Сохраняем в поисковый индекс $arFields["PARAMS"]["iblock_section"][] = $nav_ID; } } } //Всегда возвращаем arFields return $arFields; } }<? global $arSectionFilter; $arSectionFilter = array("PARAMS" => array("iblock_section" => $SECTION_ID)); ?> <?$APPLICATION->IncludeComponent( "bitrix:search.page", "tags", Array( "RESTART" => "N", "CHECK_DATES" => "Y", "arrWHERE" => array(0=>"forum",1=>"iblock_news",2=>"iblock_articles",3=>"iblock_catalog",4=>"blog",), "FILTER_NAME" => "arSectionFilter", "arrFILTER" => array(0=>"iblock_catalog",), "arrFILTER_iblock_catalog" => array(0=>"2",), "SHOW_WHERE" => "Y", "PAGE_RESULT_COUNT" => "10", "CACHE_TYPE" => "A", "CACHE_TIME" => "3600", "TAGS_SORT" => "NAME", "TAGS_PAGE_ELEMENTS" => "20", "TAGS_PERIOD" => "", "TAGS_URL_SEARCH" => "", "TAGS_INHERIT" => "Y", "FONT_MAX" => "50", "FONT_MIN" => "10", "COLOR_NEW" => "000000", "COLOR_OLD" => "C8C8C8", "PERIOD_NEW_TAGS" => "", "SHOW_CHAIN" => "Y", "COLOR_TYPE" => "Y", "WIDTH" => "100%" ) );?>Что не так?
то все работает. Т.е. почему-то не отрабатывает код
$nav = CIBlockSection::GetNavChain(2, $arSection["ID"]); while($nav->ExtractFields("nav_")) { //Сохраняем в поисковый индекс $arFields["PARAMS"]["iblock_section"][] = $nav_ID; }Может вы знаете, что ему нужно?
Почему-то не работает метод ExtractFields, а вот если сделать Fetch() то всё ок.
Спасибо за статью, очень помогло
Что-то не возьму в толк...
Подскажите пожалуйста по подробней, как у вас получилось реализовать выпадающий список рядом со строкой поиска?
Т.е. это:
<? AddEventHandler("search", "BeforeIndex", Array("CPortalHandlers", "BeforeIndexHandler")); /** * Класс для обработчиков * */ class CPortalHandlers { /** * Метод модифицирует поисковый индекс * для элементов и разделов инфоблока * */ function BeforeIndexHandler($arFields) { $IBLOCK_ID = 2; // Обрабатываем только нужный инфоблок if($arFields["MODULE_ID"] == "iblock" && $arFields["PARAM2"] == $IBLOCK_ID) { $arFields["PARAMS"]["iblock_section"] = array(); // Добавляем разделы элемента // С учетом родительских разделов if(substr($arFields["ITEM_ID"], 0, 1) != "S") { // Получаем разделы привязки элемента (их может быть несколько) $rsSections = CIBlockElement::GetElementGroups($arFields["ITEM_ID"], true); while($arSection = $rsSections->Fetch()) { $nav = CIBlockSection::GetNavChain($IBLOCK_ID, $arSection["ID"]); while($ar = $nav->Fetch()) { //Сохраняем в поисковый индекс $arFields["PARAMS"]["iblock_section"][] = $ar['ID']; } } } // Добавляем разделы раздела // С учетом родительских разделов else { // Получаем разделы $nav = CIBlockSection::GetNavChain($IBLOCK_ID, substr($arFields["ITEM_ID"], 1, strlen($arFields["ITEM_ID"]))); while($ar = $nav->Fetch()) { //Сохраняем в поисковый индекс $arFields["PARAMS"]["iblock_section"][] = $ar['ID']; } } } //Всегда возвращаем arFields return $arFields; } } ?>например, в where я получу еще и код секции (из адресной строки придет where=iblock_lists_27_131)
и обработав это значение, вытащу id секции и передам ее в $arSectionFilter. будет ли работать?
Отчего так???
Вопрос снимется.
Понял, недоиндексировались разделы,слишком долгая получается преиндексация для всех инфоблоков(вот и отключил на полпути ее), а для одного id_block никак нельзя сделать переиндексацию?
поиск используется по нескольким инфоблокам сразу, но упорно продолжает выводить деактивированные элементы...
Решил вот так:
в init.php:
AddEventHandler("search", "BeforeIndex", Array("MyClass", "BeforeIndexHandler";)); class MyClass { function BeforeIndexHandler($arFields) { if(!CModule::IncludeModule("iblock";)) // подключаем модуль return $arFields; if($arFields["MODULE_ID"] == "iblock" && $arFields["PARAM2"] == 8 && substr($arFields["ITEM_ID"], 0, 1) != "S";) { $arSelect = Array("ID", "NAME", "IBLOCK_ID", "CATALOG_QUANTITY";); $arFilter = Array("IBLOCK_ID"=>$arFields["PARAM2"], "ID"=>$arFields["ITEM_ID"]); $res = CIBlockElement::GetList(Array(), $arFilter, false, false, $arSelect); while($ob = $res->GetNextElement()){ $arElement = $ob->GetFields(); $arFields["PARAMS"]["ACTIVE"][] = $arElement["CATALOG_QUANTITY"]>0?"Y":"N"; } } return $arFields; } }перед подключением search.page:
global $arSectionFilter; $arSectionFilter = array("PARAMS" => array("ACTIVE" => "Y";));в параметрах search.page:
1) init.php (Спасибо ):
<? AddEventHandler("search", "BeforeIndex", Array("CPortalHandlers", "BeforeIndexHandler")); /** * Класс для обработчиков * */ class CPortalHandlers { /** * Метод модифицирует поисковый индекс * для элементов и разделов инфоблока * */ function BeforeIndexHandler($arFields) { $IBLOCK_ID = SANTEHVOZ_CATALOG_ID; // Обрабатываем только нужный инфоблок if($arFields["MODULE_ID"] == "iblock" && $arFields["PARAM2"] == $IBLOCK_ID) { $arFields["PARAMS"]["iblock_section"] = array(); // Добавляем разделы элемента // С учетом родительских разделов if(substr($arFields["ITEM_ID"], 0, 1) != "S") { // Получаем разделы привязки элемента (их может быть несколько) $rsSections = CIBlockElement::GetElementGroups($arFields["ITEM_ID"], true); while($arSection = $rsSections->Fetch()) { $nav = CIBlockSection::GetNavChain($IBLOCK_ID, $arSection["ID"]); while($ar = $nav->Fetch()) { //Сохраняем в поисковый индекс $arFields["PARAMS"]["iblock_section"][] = $ar['ID']; } } } // Добавляем разделы раздела // С учетом родительских разделов else { // Получаем разделы $nav = CIBlockSection::GetNavChain($IBLOCK_ID, substr($arFields["ITEM_ID"], 1, strlen($arFields["ITEM_ID"]))); while($ar = $nav->Fetch()) { //Сохраняем в поисковый индекс $arFields["PARAMS"]["iblock_section"][] = $ar['ID']; } } } //Всегда возвращаем arFields return $arFields; } } ?><?require($_SERVER["DOCUMENT_ROOT"]."/bitrix/header.php"); global $arSectionFilter; $arSectionFilter = array("PARAMS" => array("iblock_section" => $_GET['idcatalog'])); if ($_GET['idcatalog']!=''){ $arSectionFiltername = 'arSectionFilter'; }// Это условие для пункта 'Все категории', если оно выбрано то в $_GET['idcatalog'] передается пустое значение $APPLICATION->SetTitle("Поиск");?><?$APPLICATION->IncludeComponent( "santehvoz:search.page", "", Array( "USE_SUGGEST" => "N", "PATH_TO_USER_PROFILE" => "", "FILTER_NAME" => $arSectionFiltername, "arrFILTER" => array(0=>"iblock_catalog",), "arrFILTER_iblock_catalog" => array(0=>"1",), "AJAX_MODE" => "N", "RESTART" => "N", "NO_WORD_LOGIC" => "N", "USE_LANGUAGE_GUESS" => "Y", "CHECK_DATES" => "N", "USE_TITLE_RANK" => "N", "DEFAULT_SORT" => "rank", "SHOW_WHERE" => "Y", "arrWHERE" => array(), "SHOW_WHEN" => "N", "PAGE_RESULT_COUNT" => "50", "CACHE_TYPE" => "N", "CACHE_TIME" => "3600", "DISPLAY_TOP_PAGER" => "Y", "DISPLAY_BOTTOM_PAGER" => "Y", "PAGER_TITLE" => "Результаты поиска", "PAGER_SHOW_ALWAYS" => "Y", "PAGER_TEMPLATE" => "", "AJAX_OPTION_JUMP" => "N", "AJAX_OPTION_STYLE" => "Y", "AJAX_OPTION_HISTORY" => "N" ) );?> <?require($_SERVER["DOCUMENT_ROOT"]."/bitrix/footer.php");?><? $arFilter = Array('IBLOCK_ID'=>'ID каталога, у меня 1', 'GLOBAL_ACTIVE'=>'Y'); $db_list = CIBlockSection::GetList(Array($by=>$order), $arFilter, true); while($ar_result = $db_list->GetNext()) { if($ar_result['IBLOCK_SECTION_ID']=='' ){ $droplist[$ar_result['ID']]=$ar_result['NAME']; } // debugmessage($ar_result); } ?> <?if($arParams["SHOW_WHERE"]):?> <select id="type" name="idcatalog"> <option value=""><?=GetMessage("SEARCH_ALL")?></option> <?foreach($droplist as $key=>$value):?> <option value="<?=$key?>"<?if($_GET['idcatalog']==$key) echo " selected"?>><?=$value?></option> <?endforeach?> </select> <?endif;?>global $arSectionFilter; $arSectionFilter = array("PARAMS" => array("iblock_section" => 6759));Так не работает:
global $arSectionFilter; $arSectionFilter = array("PARAMS" => array("!iblock_section" => 6759));в таблице индексации b_search_content не мог найти поля PARAMS, в дкументации тоже нет . То есть в какую таблиу и поле записывается id раздела? версия 14.5