Применение поисков в разработке. Обзор нахождения критериев поиска при разработке.

15 4

Проведем разбор на основе примера поиска документов.

  Search = Searches.CereateNew(ckEDocument)

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

  Search = Searches.CreateNew(ckEDocument)
  
  Description = ''
  RequisiteDescriptionList = Search.RequisiteDescriptionList
  foreach RequisiteDescription in RequisiteDescriptionList
    CurrentRequisiteName = RequisiteDescription.Name
    CurrentRequisiteTitle = RequisiteDescription.Title 
    Description = Description &  Format('%s/%s'; ArrayOf(CurrentRequisiteName; CurrentRequisiteTitle)) & CR
  endforeach
  EditText(Description) 

Выполнив такой сценарий мы получаем все возможные имена реквизитов поиска и их осмысленное описание:

Как использовать реквизиты поиска описано в справке. Но что, если реквизитов поиска не достаточно ?

В этом случае нужно использовать AddWhere. Здесь нужно помнить, что AddWhere поиска в отличие от AddWhere справочника, это свойство, а не метод. Т.е. для справочника мы пишем условие в скобочках, а для поиска через равно.

Для дополнения условий поиска нужно знать к чему его прменять, т.е. нужно знать алиас таблицы в запросе поиска на сервер. Т.к. мы добавляем условие ограничения, его нужно добавлять именно к общим уловиям. Если в справочниках имеется для этого IReference.TableName, то для поисков этого нет, и приходится выкручиваться подручными средствами, для этого:

  • Создадим простой поиск:
  DOCUMENT_ID = 578888
  Search = Searches.CreateNew(ckEDocument)
  SearchCriteria = Search.SearchCriteria
  IntCrit = SearchCriteria.Add('ИД')
  IntCrit.SetSimpleValue(DOCUMENT_ID)
  Search.Show(ssmBrowse; FALSE)
  • Отловим его запрос профайлером:
select distinct
  1 as ObjectKind,
  MBEDocType.Kod as ComponentCode,
  MBEDocType.Name as ComponentName,
  EDocuments.XRecID as ObjectID,
  EDocuments.Name as ObjectName,
  null as FolderContentKindCode,
  EDocuments.CreateDate as Created,
  EDocuments.ModifyDate as Modified,
  EDocuments.Author as AuthorID,
  EDocuments.Editor as EditorID,
  null as FolderTypeCode,
  Statuses.Status as UserObjectStatusCode,
    case
    when exists(
     (select
        1
      from
        SBLinks BoundDocs,
        SBEDocAcc BoundDocRights,
        SBEDoc BoundDocuments
      where
        BoundDocs.SourceSystemCode is null
        and BoundDocs.SourceType = 'E'
        and BoundDocs.SourceID = EDocuments.XRecID
        and BoundDocs.DestType = 'E'
        and BoundDocuments.XRecID = BoundDocs.DestID
        and BoundDocRights.EDocID = BoundDocuments.XRecID
        and BoundDocuments.EncodeType = 'Н')) then 1
    when exists(
     (select
        1
      from
        SBLinks BoundDocs,
        SBEDocAcc BoundDocRights,
        SBEDoc BoundDocuments
      where
        BoundDocs.SourceSystemCode is null
        and BoundDocs.DestType = 'E'
        and BoundDocs.DestID = EDocuments.XRecID
        and BoundDocs.SourceType = 'E'
        and BoundDocuments.XRecID = BoundDocs.SourceID
        and BoundDocRights.EDocID = BoundDocuments.XRecID
        and BoundDocuments.EncodeType = 'Н')) then 1
    when exists(
     (select
        1
      from
        SBLinks BoundDocs,
        SBEDocAcc BoundDocRights
      where
        BoundDocs.SourceSystemCode is null
        and BoundDocs.SourceType = 'E'
        and BoundDocs.SourceID = EDocuments.XRecID
        and BoundDocs.DestType = 'E'
        and BoundDocRights.EDocID = BoundDocs.DestID
        and BoundDocRights.AccountID = 103576)) then 1
    when exists(
     (select
        1
      from
        SBLinks BoundDocs,
        SBEDocAcc BoundDocRights
      where
        BoundDocs.SourceSystemCode is null
        and BoundDocs.DestType = 'E'
        and BoundDocs.DestID = EDocuments.XRecID
        and BoundDocs.SourceType = 'E'
        and BoundDocRights.EDocID = BoundDocs.SourceID
        and BoundDocRights.AccountID = 103576)) then 1
  else
    0
  end as HasBoundDocuments,
  EDocuments.Signed as Signed,
  EDocuments.SignatureType as SignatureType,
  EDocuments.Extractor as ExporterID,
  'П' as UserDeaObjectAccessRightsCode,
  null as HasChildren,
  EDocuments.EncodeType as EncodeType,
  EDocuments.Storage as StorageID,
  EDocuments.TypeID as CardType,
  EDocuments.Kind as EDocKind,
  EDocuments.TextModifyDate as TextModifyDate,
  EDocuments.LifeStageName as LifeCycleStageName
from
  SBEDoc EDocuments,
  MBEDocType MBEDocType,
  SBMarkPerfomance Statuses,
  SBEDocAcc AccessRights
where
  EDocuments.TypeID = MBEDocType.TypeID
  and Statuses.SourceID =* EDocuments.XRecID
  and Statuses.UserID = 103576
  and Statuses.SourceType = 'E'
  and ((Statuses.Status <> 'S') and (Statuses.Status <> 'C'))
  and AccessRights.EDocID = EDocuments.XRecID
  and ((EDocuments.EncodeType = 'Н') or (AccessRights.AccountID = 103576))
  and EDocuments.XRecID = 578888
order by
  ObjectName
  • Видим все используемые алиасы:
from
  SBEDoc EDocuments,
  MBEDocType MBEDocType,
  SBMarkPerfomance Statuses,
  SBEDocAcc AccessRights
  • И теперь имеем возможность их использовать

Например, нужно найти либо документы со значением А1 реквизита А либо документы со значением Б1 реквизита Б одновременно. Например, реквизит А - это автор документа, значение А1 - 105825, реквизит Б - это приложение редактор, а его значение Б1 - 44874. Т.е. мы должны получить документы у которых либо автор с ИД 105825, либо ИД приложения редактора 44874.

  DOCUMENTS_ALIAS = 'EDocuments'

  Search = Searches.CreateNew(ckEdocument)
  SearchCriteria = Search.SearchCriteria
  SearchCriteria.AddWhere = Format('(%0:s.Author = 105825 or %0:s.Editor = 44874)'; DOCUMENTS_ALIAS)
  Search.Show(ssmBrowse; FALSE)

Таким образом мы построили поиск, который нет возможности выполнить через cтандартные механизмы.

Петр Федотов

 

Важным моментом, при использовании оператора or в строке условия AddWhere, является наличие скобок. Т.к. если скобки не указать, общий запрос будет выглядеть как 
...
where
  EDocuments.TypeID = MBEDocType.TypeID
  and Statuses.SourceID =* EDocuments.XRecID
  and Statuses.UserID = 103576
  and Statuses.SourceType = 'E'
  and ((Statuses.Status <> 'S') and (Statuses.Status <> 'C'))
  and AccessRights.EDocID = EDocuments.XRecID
  and ((EDocuments.EncodeType = 'Н') or (AccessRights.AccountID = 103576))
  and EDocuments.XRecID = 578888
  and <первое условие> 
  or <второе условие> 
такой запрос просто "повесит" систему, т.к. будет выполнятся очень долго
Андрей Куров

Ищу материал по справочнику поиски, наткнулся на этот материал.

Небольшое замечание:

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

Использовать edittext() для показа легальных реквизитов, профайлер и алиасы для построения сложного поиска? Нет, спасибо [Image]. Набросать Select куда как проще, благо база открытая и структура несложная.
Ну и бесплатный плюс - свой собственный селект отработает всяко быстрее, чем поиск с использованием объектной модели.
Иван Чурбаков

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

У собственного запроса есть существенный недостаток: он не учитывает права доступа.

Андрей Куров

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

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

Авторизуйтесь, чтобы написать комментарий