Выборки

Для осуществления выборок из ссылочных коллекций реализован класс "Селектор". Селектор позволяет:

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

Создать селектор можно:

  • вызвав метод "СоздатьСелектор()" объекта "БромКлиент";
  • вызвав метод "СоздатьСелектор()" модуля менеджера соответствующей коллекции.

Формирование выборки происходит:

  • при вызове метода "Выполнить()" селектора;
  • при получении итератора селектора "getIterator()".

Селектор может формировать выборки для следующих коллекций:

  • Справочники;
  • Документы;
  • Перечисления;
  • Планы видов характеристик;
  • Планы счетов;
  • Планы видов расчета;
  • Бизнес-процессы;
  • Задачи.
// Выборка всех элементов справочника "Номенклатура"
$текСелектор = $клиент->СоздатьСелектор();

$текСелектор->УстановитьКоллекцию("Справочник.Номенклатура");
$текСелектор->АвтозагрузкаПолей = АвтозагрузкаПолейОбъектов::ТолькоСтандартныеРеквизиты();

foreach ($текСелектор as $текСсылка) {
	echo("Наименование: {$текСсылка->Наименование}; Код: {$текСсылка->Код} <br/>");
}

// Добавляем отбор и дозапрашиваем данные производителя
$текСелектор->ДобавитьОтбор("ЭтоГруппа", false);
$текСелектор->ДобавитьСортировку("Наименование");
$текСелектор->ДобавитьПоля("Производитель, Производитель.ИНН");

foreach ($текСелектор as $текСсылка) {
	echo("
		Наименование: {$текСсылка->Наименование}; 
		Код: {$текСсылка->Код}; 
		Производитель: {$текСсылка->Производитель}; 
		ИНН: {$текСсылка->Производитель->ИНН} <br/>
	");
}

// Сохраняем результат выборки в массив для последующего использования
$результат = $текСелектор->ВыгрузитьРезультат();
// Выборка из справочника "Номенклатура" в стиле языка запросов
$текСелектор = $клиент->СоздатьСелектор();

$текСелектор->
	Выбрать("Наименование, Код, Производитель, Производитель.ИНН")->
	Первые(20)->
	Из("Справочник.Номенклатура")->
	Где("ЭтоГруппа", false)->
	Где("Родитель.Наименование", "Мебель")->
	Упорядочить("Наименование");

foreach ($текСелектор as $текСсылка) {
	echo("
		Наименование: {$текСсылка->Наименование}; 
		Код: {$текСсылка->Код}; 
		Производитель: {$текСсылка->Производитель}; 
		ИНН: {$текСсылка->Производитель->ИНН} <br/>
	");
}

// Сохраняем результат выборки в массив для последующего использования
$результат = $текСелектор->ВыгрузитьРезультат();
// Выборка номенклатуры из группы "Мебель"
$группаМебель = $клиент->Справочники->Номенклатура->НайтиПоНаименованию("Мебель");

$текСелектор = $клиент->Справочники->Номенклатура->СоздатьСелектор();

$текСелектор->
	Выбрать("Наименование, Код, Производитель, Производитель.ИНН")->
	Где("ЭтоГруппа", false)->
	Где("Ссылка", $группаМебель, ВидСравнения::ВИерархии())->
	Упорядочить("Производитель")->
	Упорядочить("Наименование", НаправлениеСортирвки::Убывание());

foreach ($текСелектор as $текСсылка) {
	echo("
		Наименование: {$текСсылка->Наименование}; 
		Код: {$текСсылка->Код}; 
		Производитель: {$текСсылка->Производитель}; 
		ИНН: {$текСсылка->Производитель->ИНН} <br/>
	");
}

// Сохраняем результат выборки в массив для последующего использования
$результат = $текСелектор->ВыгрузитьРезультат();
// Выборка заказов с определенной даты, в которых есть товары из раздела "Мебель"
$группаМебель = $клиент->Справочники->Номенклатура->НайтиПоНаименованию("Мебель");

$текСелектор = $клиент->Документы->ЗаказКлиента->СоздатьСелектор();

$текСелектор.
	Выбрать("Дата, Номер, Контрагент")->
	Где("Проведен", true)->
	Где("Дата", new DateTime(2019, 1, 1), ВидСравнения::БольшеИлиРавно())->
	Где("Товары.Номенклатура", $группаМебель, ВидСравнения::ВИерархии())->
	Упорядочить("Контрагент")->
	Упорядочить("Дата", НаправлениеСортирвки::Убывание());

foreach ($текСелектор as $текСсылка) {
	echo("Дата: {$текСсылка->Дата}; Номер: {$текСсылка->Номер}; Контрагент: {$текСсылка->Контрагент} <br/>");
}

// Сохраняем результат выборки в массив для последующего использования
$результат = $текСелектор->ВыгрузитьРезультат();

Установка отборов

Установить отбор селектора можно:

  • вызвав метод "ДобавитьОтбор()" селектора;
  • вызвав метод "Где()" селектора (метод является синонимом).

В качестве параметров метода необходимо указать:

  • Ключ поля (путь к данным поля), например "Ссылка", "Артикул", "Производитель.ИНН", "Родитель.Наименование". Допускается указывать путь к данным реквизитов табличных частей, например "Товары.Количество", "ДополнительныеРеквизиты.Свойство.Наименование" и тд...
  • Значене сравнения сериализуемого типа. Тип значения должен соответствовать реквизиту;
  • Вид сравнения (опционально, по умолчанию "Равно"). Вид сравнения может быть:
    • Равно;
    • НеРавно;
    • Больше;
    • БольшеИлиРавно;
    • Меньше;
    • МеньшеИлиРавно;
    • Содержит;
    • НеСодержит;
    • ВСписке;
    • НеВСписке;
    • ВИерархии;
    • НеВИерархии.

Для видов сравнения "ВСписке" и "НеВСписке" в качестве значения необходимо передавать массив значений (array или Массив). Для видов сравнения "ВИерархии" и "НеВИерархии" можно передавать как одно значение (ссылку), так и массив значений (массив ссылок).

// Пример отборов для справочника
$текСелектор->ДобавитьОтбор("Артикул", "Т-0001");
$текСелектор->ДобавитьОтбор("Вес", 15, ВидСравнения::БольшеИлиРавно());
$текСелектор->ДобавитьОтбор("Ссылка", $группаМебель, ВидСравнения::НеВИерархии());
$текСелектор->ДобавитьОтбор(
	"Производитель.Родитель", 
	Массив::ИзМассива(array($ссылка1, $ссылка2, $ссылка3)), 
	ВидСравнения::ВСписке()
);
// Пример отборов для документа
$текСелектор->
	Где("Дата", new Дата("2019-01-01"), ВидСравнения::БольшеИлиРавно())->
	Где("Товары.Номенклатура", array($ссылка1, $ссылка2, $ссылка3), ВидСравнения::ВСписке())->
	Где("Проведен", true, ВидСравнения::Равно())->
	Где("ДокументОснование", $клиент->Документы->ЗаказКлиента->ПустаяСсылка(), ВидСравнения::НеРавно());

Сортировка выборок

Указать сортировку выборки можно:

  • вызвав метод "ДобавитьСортировку()" селектора;
  • вызвав метод "Упорядочить()" селектора (метод является синонимом).

В качестве параметров метода необходимо указать:

  • Ключ поля (путь к данным поля), например "Наименование", "Артикул", "Производитель.Код", "Родитель.Наименование" и тд..;
  • Направление сортировки (опционально, по умолчанию "Возрастание").
$текСелектор->ДобавитьСортировку("Наименование");
$текСелектор->ДобавитьСортировку("Производитель.Наименование", НаправлениеСортирвки::Убывание());
$текСелектор->
	Упорядочить("Дата", НаправлениеСортирвки::Убывание())->
	Упорядочить("Контрагент");

Загрузка контекстных данных

Сам по себе селектор является коллекцией ссылок, реализующей интерфейсы "IteratorAggregate", "ArrayAccess", "Countable". В некоторых случаях возникает необходимость получения доступа к контекстным данным объектов (к данным реквизитов и табличных частей), на которые эти ссылки указывают. Доступ к данным может быть получен путем обращения к динамическим полям ссылки, например "текСсылка.Артикул", однако при таком обращении будет отправлен запрос серверу с последующей загрузкой полного набора контекстных данных. Чтобы избежать множественных запросов к серверу и избыточной загрузки данных, в классе селектора предусмотрена возможность указания полей объекта, которые должны быть загружены единовременно вместе с формированием выборки.

Указать дополнительные поля выборки можно:

  • вызвав метод "ДобавитьПоля()" селектора;
  • вызвав метод "Выбрать()" селектора (метод является синонимом).

В качестве параметров метода необходимо указать список полей, данные которых необходимо загрузить. Могут быть указаны как поля самого объекта выборки, так и подчиненные поля, например "Производитель.Родитель.Наименование", "Контрагент.ИНН" и тд...

// Неоптимальный вариант работы с данными
$текСелектор = $клиент->Справочники->Номенклатура->СоздатьСелектор();

foreach ($текСелектор as $текСсылка) {
	echo("Наименование: {$текСсылка->Наименование}; Производитель: {$текСсылка->Производитель} <br/>");

	// В каждой итерации будет происходить два запроса на сервер:
	//  - запрос на получение ВСЕХ контекстных данных ссылки "текСсылка", включая данные табличных частей;
	//  - запрос на получение ВСЕХ контекстных данных ссылки "Производитель" для формирования представления ссылки.
	// Это медленно и крайне неэффективно!
}
// Оптимальный вариант работы с данными
$текСелектор = $клиент->Справочники->Номенклатура->СоздатьСелектор();

$текСелектор->ДобавитьПоля("Наименование, Производитель");

foreach ($текСелектор as $текСсылка) {
	echo("Наименование: {$текСсылка->Наименование}; Производитель: {$текСсылка->Производитель} <br/>");

	// Дополнительных запросов на сервер происходить не будет, 
	// т.к. необходимые данные уже загружены с сервера и помещены в контекст
}
$текСелектор = $клиент->Справочники->Номенклатура->СоздатьСелектор();

// Запрашиваем данные, которые понадобятся для дальнейшей работы 
$текСелектор->
	Выбрать("Наименование, Родитель.Код, Производитель.Родитель.Наименование")->
	Выбрать("ПометкаУдаления, ДополнительныеРеквизиты");

foreach ($текСелектор as $текСсылка) {
	// TODO
}

В классе селектора также предусмотрено свойство "АвтозагрузкаПолей", которое позволяет указать, какие именно данные необходимо загружать вместе с выборкой, без указания конкретных имен полей.

// Будут загружены данные только стандартных реквизитов
$текСелектор->АвтозагрузкаПолей = АвтозагрузкаПолейОбъектов::ТолькоСтандартныеРеквизиты();
// Будут загружены данные всех реквизитов объекта (без табличных частей)
$текСелектор->АвтозагрузкаПолей = АвтозагрузкаПолейОбъектов::ТолькоРеквизиты();
// Будут загружены все данные объекта (реквизиты и табличные части)
$текСелектор->АвтозагрузкаПолей = АвтозагрузкаПолейОбъектов::ВсеПоля();

Подробная информация по работе со ссылками и контекстными данными ссылок представлена в разделе "Работа со ссылками".

Ограничение размера выборки

Ограничить количество выбираемых элементов можно:

  • установив свойство "Лимит";
  • вызвав метод "Первые()".
$текСелектор->Лимит = 10;
$текСелектор->Первые(10);