Разработка и Конфигурация · 10 мин
Как работает поиск по реквизиту в 1С: метод НайтиПоРеквизиту
Как работает метод НайтиПоРеквизиту в 1С: синтаксис, примеры кода, отличие от НайтиПоКоду и НайтиПоНаименованию, типичные ошибки и отладка поиска.
Метод НайтиПоРеквизиту — один из базовых инструментов разработчика 1С для поиска элемента справочника, плана видов характеристик, плана счетов или плана видов расчёта по значению произвольного реквизита. В отличие от поиска по коду или наименованию, он позволяет обратиться к любому реквизиту объекта, включая те, что добавлены в конфигурацию вручную.
Метод возвращает ссылку на найденный объект. Если подходящих элементов несколько, возвращается первый найденный — какой именно, платформа не гарантирует. Если ничего не найдено, возвращается пустая ссылка соответствующего типа, и это обязательно нужно проверять перед использованием результата.
Поиск выполняется только среди непомеченных на удаление объектов и только по реквизитам, для которых в конфигураторе установлено свойство «Индексировать» (или реквизит входит в индекс). Если индексирование не включено, метод всё равно сработает, но поиск будет медленным на больших таблицах, а в ряде случаев разработчики ошибочно считают, что метод «не работает».
Синтаксис и параметры метода
Полная сигнатура метода выглядит так:
НайденнаяСсылка = Справочники.Номенклатура.НайтиПоРеквизиту(
"Артикул", // имя реквизита (строка)
"ТОВ-00125", // искомое значение
, // родитель (для иерархических справочников)
);
Параметры метода:
- Имя реквизита — строка с именем реквизита, как оно задано в конфигураторе. Регистр букв не важен, но опечатка в имени вызовет ошибку выполнения.
- Значение — искомое значение. Тип должен совпадать с типом реквизита: для реквизита типа «Строка» передавайте строку, для ссылочного реквизита — ссылку.
- Родитель — необязательный параметр для иерархических справочников: поиск ограничивается элементами внутри указанной группы.
- Владелец — необязательный параметр для подчинённых справочников: поиск ведётся только среди элементов, подчинённых указанному владельцу.
Как проверить результат поиска
Самая частая ошибка новичков — использовать результат поиска без проверки. Если элемент не найден, обращение к реквизитам пустой ссылки вызовет ошибку или приведёт к записи некорректных данных в базу.
НайденнаяСсылка = Справочники.Контрагенты.НайтиПоРеквизиту("ИНН", ИНН);
Если НайденнаяСсылка.Пустая() Тогда
// Элемента нет — создаём новый или сообщаем пользователю
Сообщить("Контрагент с ИНН " + ИНН + " не найден");
Иначе
// Работаем с найденным объектом
ОбъектКонтрагента = НайденнаяСсылка.ПолучитьОбъект();
КонецЕсли;
Обратите внимание: метод возвращает ссылку, а не объект. Чтобы изменить данные элемента, нужно вызвать ПолучитьОбъект(), внести изменения и записать. Для чтения реквизитов на форме или в отчёте часто достаточно обращения через точку к ссылке — платформа сама выполнит обращение к базе, но в циклах это порождает множество запросов и замедляет код.
Отличие от НайтиПоКоду и НайтиПоНаименованию
Все три метода решают одну задачу — получить ссылку на элемент, — но работают с разными полями и имеют разные ограничения.
| Метод | По какому полю ищет | Особенности |
|---|---|---|
| НайтиПоКоду | Код элемента | Быстрый, код обычно уникален; есть параметр поиска по полному коду с учётом иерархии |
| НайтиПоНаименованию | Наименование | Требует точного совпадения строки; наименования могут дублироваться |
| НайтиПоРеквизиту | Любой реквизит | Гибкий, но требует индексирования реквизита для приемлемой скорости |
Правило выбора простое: если ищете по коду — используйте НайтиПоКоду, по наименованию — НайтиПоНаименованию, по любому другому полю (ИНН, артикул, штрихкод, GUID-подобный идентификатор) — НайтиПоРеквизиту. Не подменяйте один метод другим: поиск ИНН через НайтиПоНаименованию не сработает, потому что ИНН хранится в отдельном реквизите.
Роль индексирования реквизита
Платформа выполняет поиск по реквизиту через индекс базы данных. Если у реквизита в конфигураторе не установлено свойство «Индексировать» (или «Индексировать с дополнительным упорядочиванием»), поиск будет выполняться полным перебором таблицы. На справочнике в несколько тысяч элементов это незаметно, на миллионе записей — приведёт к заметным паузам и блокировкам.
Чтобы включить индексирование, откройте конфигуратор, найдите нужный реквизит справочника и в палитре свойств установите «Индексировать». После этого потребуется обновить конфигурацию базы данных — платформа создаст индекс. На больших таблицах реструктуризация может занять продолжительное время, поэтому в рабочих базах её выполняют в нерабочие часы.
Поиск в иерархических и подчинённых справочниках
Если справочник иерархический, параметр «Родитель» сужает область поиска до одной группы. Это полезно, когда одинаковые значения реквизита допустимы в разных ветках: например, артикул может повторяться у поставщиков, и поиск ведётся только внутри группы конкретного поставщика.
ГруппаОборудование = Справочники.Номенклатура.НайтиПоНаименованию("Оборудование");
Ссылка = Справочники.Номенклатура.НайтиПоРеквизиту("Артикул", Артикул, ГруппаОборудование);
Для подчинённых справочников (например, «Договоры контрагентов», подчинённый «Контрагентам») параметр «Владелец» обязателен к осмысленному заполнению: без него поиск идёт по всем элементам всех владельцев, и вы можете получить договор совершенно другого контрагента с совпадающим номером.
ДоговорСсылка = Справочники.ДоговорыКонтрагентов.НайтиПоРеквизиту(
"НомерДоговора", НомерДоговора, , КонтрагентСсылка);
- 1Убедитесь, что реквизит проиндексирован в конфигураторе
- 2Выполните НайтиПоРеквизиту с нужными параметрами (родитель, владелец)
- 3Проверьте результат: Если Ссылка.Пустая() Тогда ...
- 4Если элемент не найден — создайте новый через СоздатьЭлемент()
- 5Если найден — получите объект через ПолучитьОбъект(), измените и запишите
- 6Проверьте результат в пользовательском режиме на тестовой копии
Типичные ошибки и их последствия
Первая ошибка — несовпадение типов. Если реквизит имеет тип «Строка(10)», а вы ищете число, метод вернёт пустую ссылку, даже если «визуально» значения совпадают. То же касается лишних пробелов: строка « ТОВ-125 » с пробелом не равна «ТОВ-125». При загрузке данных из внешних источников значения стоит обрезать функцией СокрЛП().
Вторая ошибка — поиск по неуникальному реквизиту без дополнительной логики. Если по ИНН в базе заведено два контрагента (дубль), метод молча вернёт один из них, и документы могут быть оформлены не на того контрагента. Для критичных интеграций лучше использовать запрос с проверкой количества найденных элементов.
Третья ошибка — использование метода в цикле при обработке больших массивов данных. Каждый вызов — отдельное обращение к базе. При загрузке тысяч строк эффективнее один запрос с соединением таблицы значений или временной таблицей.
Альтернатива: поиск запросом
Когда нужно найти все элементы с заданным значением реквизита, проверить дубли или искать сразу по нескольким условиям, метод НайтиПоРеквизиту не подходит — используйте запрос:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Контрагенты.Ссылка КАК Ссылка
|ИЗ
| Справочник.Контрагенты КАК Контрагенты
|ГДЕ
| Контрагенты.ИНН = &ИНН
| И НЕ Контрагенты.ПометкаУдаления";
Запрос.УстановитьПараметр("ИНН", ИНН);
Результат = Запрос.Выполнить().Выгрузить();
Если Результат.Количество() > 1 Тогда
Сообщить("Найдено несколько контрагентов с ИНН " + ИНН);
КонецЕсли;
Запрос даёт полный контроль: можно отобрать всех дублей, добавить условия по другим полям, упорядочить результат и использовать конструкцию ВЫБРАТЬ ПЕРВЫЕ 1 как аналог НайтиПоРеквизиту с явной логикой выбора.
Как проверить результат
Ссылка не пустая, реквизиты читаются
Пустая ссылка — элемент не найден или тип значения не совпал
Поиск мгновенный даже на большом справочнике
Заметная пауза — проверьте индексирование реквизита
Запрос по тому же условию возвращает одну строку
Несколько строк — есть дубли, метод вернул случайный элемент
FAQ: частые вопросы о поиске по реквизиту
Почему НайтиПоРеквизиту возвращает пустую ссылку, хотя элемент точно есть?
Чаще всего дело в несовпадении типа значения с типом реквизита, лишних пробелах или в том, что элемент помечен на удаление — помеченные объекты метод игнорирует. Также проверьте, не передан ли родитель или владелец, ограничивающий область поиска.
Можно ли искать по нескольким реквизитам одновременно?
Нет, метод принимает только одно имя реквизита. Для поиска по комбинации условий используйте запрос с несколькими условиями в секции ГДЕ.
Работает ли метод с табличными частями элемента?
Нет, поиск ведётся только по реквизитам шапки объекта. Чтобы найти элемент по значению в табличной части, нужен запрос с обращением к табличной части справочника.
Что быстрее: НайтиПоРеквизиту или запрос?
При проиндексированном реквизите разница для одиночного поиска несущественна. Запрос выигрывает при поиске по нескольким условиям и в циклах, где можно обработать весь массив одним обращением к базе.
Как найти элемент по реквизиту с частичным совпадением строки?
НайтиПоРеквизиту ищет только точное совпадение. Для поиска по подстроке используйте запрос с оператором ПОДОБНО и шаблоном с символами процента, например: ГДЕ Наименование ПОДОБНО "%фрагмент%".
Найдёт ли метод элемент в другой группе иерархического справочника?
Если параметр «Родитель» не задан, поиск идёт по всему справочнику независимо от иерархии. Если родитель указан — только среди элементов, непосредственно входящих в эту группу.
Что важно запомнить
НайтиПоРеквизиту ищет один элемент справочника по точному значению любого реквизита и возвращает ссылку. Всегда проверяйте результат на пустую ссылку, следите за типом значения и индексированием реквизита, а для поиска по нескольким условиям или контроля дублей используйте запрос.