Каталог решений - Быстрый поиск средствами библиотеки ToySQL

Быстрый поиск средствами библиотеки ToySQL

Быстрый поиск средствами библиотеки ToySQL

В наличии

В заметке приведен текст процедуры, с помощью которой можно реализовать быстрый поиск в SQL базе с помощью библиотеки ToySQL.

Категория:

Описание

В ходе работы над конфигурацией заказчика столкнулись с проблемой медленного поиска в больших справочниках. Число элементов в справочниках в данный момент зашкаливает за 300 тысяч. Поиск стандартными средствами по первым буквам занимает до 10 секунд. Поиск подстроки вообще очень долго. В общем-то типовая задача для тех, кто занимается разработкой на 7-ке в SQL. И в общем-то эта задача уже решалась не раз — с помощью 1С++ или с помощью других средств. В каком-то смысле это изобретение велосипеда. В основном заметка полезна пользователям библиотеки ToySQL (хотя и на 1С++ это легко переносится). Особенность работы процедуры — поиск по подстроке в реквизитах наименование, код, а также в реквизитах с сортировкой. Есть возможность поиска по агрегатным реквизитам (поиск через точку). Результаты поиска отображаются в форме списка с помощью установки фильтра по найденным элментам, тем самым можно произвести выбор из этого списка без дополнительных выкрутасов. Встроить в модуль формы списка достаточно просто — добавляем на форму кнопку поиска с вызовом:

глБыстрыйПоиск(Контекст,Синонимы,,ДопРеквизиты)

Текст основной и вспомогательных процедур:

Функция ПолучитьСиноним(Синоним,Синонимы)

    Если Синонимы = 0 Тогда

        Возврат Синоним;

    Иначе

        Стр = Синонимы.Получить(Синоним);

        Если ПустаяСтрока(Стр) = 1 Тогда

            Возврат Синоним;

        Иначе

            Возврат Стр;

        КонецЕсли;

    КонецЕсли;

КонецФункции
Функция ИсключитьИзСписка(Рекв,Список)

    Если Список = 0 Тогда

        Возврат 0;

    Иначе

        Если Список.НайтиЗначение(Рекв) > 0 Тогда

            Возврат 1;

        КонецЕсли;

    КонецЕсли;

    Возврат 0;

КонецФункции
Процедура глБыстрыйПоиск(Конт,Синонимы=0,Исключить=0,ДопРеквизиты=0) Экспорт

    РеквизитыПоиска = СоздатьОбъект("СписокЗначений");

    Вид = Конт.Вид();

    Мета = Метаданные.Справочник(Вид);

    Если Мета.ДлинаНаименования > 0 Тогда

        Если ИсключитьИзСписка("Наименование",Исключить) = 0 Тогда

            РеквизитыПоиска.ДобавитьЗначение("Наименование",ПолучитьСиноним("Наименование",Синонимы));

        КонецЕсли;

    КонецЕсли;

    Если (Мета.ДлинаКода > 0) И (Мета.ТипКода = "Текстовый") Тогда

        Если ИсключитьИзСписка("Код",Исключить) = 0 Тогда

            РеквизитыПоиска.ДобавитьЗначение("Код",ПолучитьСиноним("Код",Синонимы));

        КонецЕсли;

    КонецЕсли;

    

    Для н=1 По Мета.Реквизит() Цикл

        Рекв = Мета.Реквизит(н);

        Если Рекв.Сортировка = 1 Тогда

            Если Рекв.Тип = "Строка" Тогда

                Если ИсключитьИзСписка(Рекв.Идентификатор,Исключить) = 0 Тогда

                    РеквизитыПоиска.ДобавитьЗначение(Рекв.Идентификатор,?(ПустоеЗначение(Рекв.Синоним)=1,Рекв.Идентификатор,Рекв.Синоним));

                КонецЕсли;

            КонецЕсли;

        КонецЕсли;

    КонецЦикла;

    

    Если ПустоеЗначение(ДопРеквизиты) = 0 Тогда

        Стр = "";

        Для н=1 По ДопРеквизиты.РазмерСписка() Цикл

            Зн = ДопРеквизиты.ПолучитьЗначение(н,Стр);

            РеквизитыПоиска.ДобавитьЗначение(Зн,Стр);

        КонецЦикла;

    КонецЕсли;

    

    Зн = "";

    Если РеквизитыПоиска.ВыбратьЗначение(Зн,,,,1) = 1 Тогда

        Стр = "";

        Если ВвестиСтроку(Стр,"Введите строку поиска",50) = 1 Тогда

            п = Найти(Зн,".");

            Если п > 0 Тогда

                Рекв = Лев(Зн,п-1);

                МетаРекв = Мета.Реквизит(Рекв);

                Поиск = Рекв+"."+Сред(Зн,п+1);

                

                ТекстЗапроса = "SEL ECT [Спр.Ссылка]

                |FR OM [Справочник."+Вид+"] Спр WITH (NOLOCK)

                |JOIN ["+МетаРекв.Тип+"."+МетаРекв.Вид+"] "+Рекв+" WITH (NOLOCK) ON [Спр."+Рекв+"] = ["+Рекв+".Ссылка]

                |WHERE UPPER(["+Поиск+"]) LIKE '%"+Врег(Стр)+"%'

                |ORDER BY [Спр.Наименование]";

                

            Иначе

                ТекстЗапроса = "SEL ECT [Ссылка] FR OM [Справочник."+Вид+"] WITH (NOLOCK) WHERE UPPER(["+Зн+"]) LIKE '%"+Врег(Стр)+"%'

                |ORDER BY [Наименование]";

            КонецЕсли;

            

            Запрос = СоздатьОбъект("ToyQuery");

            Запрос.Вернуть1С = 1;

            Если Запрос.МетаЗапрос(ТекстЗапроса) = 1 Тогда

                ТЗ = СоздатьОбъект("СписокЗначений");

                Запрос.Выгрузить(ТЗ);

                Если ТЗ.РазмерСписка() > 0 Тогда

                    Конт.ИспользоватьСписокЭлементов(ТЗ);

                Иначе

                    Сообщить("Ничего не найдено");

                    Конт.ИспользоватьСписокЭлементов();

                КонецЕсли;

            Иначе

                Сообщить(Запрос.Ошибка);

            КонецЕсли;

        КонецЕсли;

    КонецЕсли;

КонецПроцедуры

has been added to your cart:
Оформление заказа