Публикация

Возможность поиска дублей по вхождению.

Добрый день всем!

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

Итак. 1. Начинаем с создания булевого системного параметра "FindDuplicatesWithLike" в клиентском приложении. По умолчанию оставляем его в значении false (стандартный поиск), если же он равен true - будем вызывать функции для поиска по вхождению.

2. В скрипте scr_SubjectDuplicates создаём функцию, аналогичную AddDetailFilter. Её предназначение - формирование условия фильтрации для поиска дублей выделенной записи по полю DataFieldName (используя like):

function AddDetailFilterLike(Select, Dataset, DataFieldName) {
    var DataField = Dataset.DataFields.ItemsByName(DataFieldName);
    var Filters = Select.Filters;
    var CompareFilter = AddLikeFieldFilter(Select, DataFieldName, DataFieldName,
        ltContain, Filters);
}

3. В этом же скрипте изменяем функцию UpdateSubjectDataset - добавляем проверку системного параметра:

function UpdateSubjectDataset() {
    var SubjectDataset = SubjectDuplicates.SubjectDataset;
    var SelectQuery = SubjectDataset.SelectQuery;
    var Select = SelectQuery.Items(0);
    Select.Filters.Clear();
    Select.Filters.ParentParametriticQuery.Parameters.Clear();
    var DataFieldNames = SubjectDuplicates.DataFieldNames;
    for(var i = 0; i DataFieldNames.length; i++) {
        var DataFieldName = DataFieldNames[i];
        var FindDuplicatesLikeParameter =
            GetSystemParameterValueEx('FindDuplicatesWithLike', true);
        if (FindDuplicatesLikeParameter) {
            AddDetailFilterLike(Select, SubjectDataset, DataFieldName);
        } else {
            AddDetailFilter(Select, SubjectDataset, DataFieldName);
        }

    }

}
 

4. С этим скриптом закончили. Все остальные изменения - в скрипте scr_DuplicatesUtils. Итак, для начала создаём функции для формирования запроса основного реестра. Одна из них формирует колонку подзапроса для подсчёта количества дублей, а вторая - для формирования условия фильтрации. Их создаём по аналогии с функциями CreateCountSelectExpression и AddCountCompareFilter:

function CreateCountSelectColumn(DuplicatesProperties, Filters, Columns,
    CheckFieldNames) {
    var SelectFromTable =
        Services.GetSingleItemByUSI(DuplicatesProperties.TableName);
    var SelectFromTableAlias = SelectFromTable.SQLName + 'Duble';
    var SelectColumn = CreateSubselectColumn(Columns);
    SelectColumn.ColumnAlias = DuplicatesCode;
    Columns.Add(SelectColumn);
    var SubSelectQuery = SelectColumn.ColumnSelectQuery;
    var ExpressionSelect = AddSelect(SubSelectQuery, SelectFromTable,
        SelectFromTableAlias);
    var ExpressionFilters = ExpressionSelect.Filters;
    var ParentFromTable = Filters.ParentSelect.FromTable;
    var ParentFromTableAlias = Filters.ParentSelect.FromTableAlias;   
    AddCountCompareFilters(ExpressionFilters, ParentFromTable,
        ParentFromTableAlias, SelectFromTable, SelectFromTableAlias,
        CheckFieldNames);
    var ExpressionColumns = ExpressionSelect.Columns;   
    var SummaryTableField =
        SelectFromTable.Fields.ItemsByName(DuplicatesCode);
    AddSummaryColumn(ExpressionColumns, DuplicatesCode,
        SummaryTableField, stCount);
    return SelectColumn;
}

function AddCountCompareFilterLike(ExpressionFilters, ParentFromTable,
    ParentFromTableAlias, SelectFromTable, SelectFromTableAlias,
    CheckFieldName) {
    var TestField = ParentFromTable.Fields.ItemsByName(CheckFieldName);
    var ValueField = SelectFromTable.Fields.ItemsByName(CheckFieldName);
    var CompareFilter = ExpressionFilters.CreateLikeFilter();
    CompareFilter.Code = GenNewKeyValueFromCollection(ExpressionFilters, 'LikeFilter');
    ExpressionFilters.Add(CompareFilter);
    CompareFilter.TestExpression = AddFieldExpression(ExpressionFilters,
        CompareFilter, TestField, SelectFromTableAlias);
    CompareFilter.LikeType = ltContain;
    CompareFilter.ValueExpression = AddFieldExpression(ExpressionFilters,
        CompareFilter, ValueField, ParentFromTableAlias);
    return CompareFilter;
}

5. Наконец, вносим изменения в функции CreateDuplicatesSelectQuery и AddCountCompareFilters - добавляем вызовы наших функций в зависимости от значения системного параметра:

function CreateDuplicatesSelectQuery(DuplicatesProperties, Table, FieldNames) {
    var CreatedQuery = Services.CreateItem(SelectQueryCode);
    var FromTableAlias = Table.SQLName + '1';
    var Select = AddSelect(CreatedQuery, Table, FromTableAlias);   
    var FieldName;
    var GeneralColumn;
    for (var i = 0; i FieldNames.length; i++) {
        FieldName = FieldNames[i];
        GeneralColumn = AddGeneralColumn(Select.Columns,
            Table.Fields.ItemsByName(FieldName), FieldName);
        GeneralColumn.OrderType = otAsc;
        GeneralColumn.OrderPosition = i + 1;
    }
    var SummaryTableField = Table.Fields.ItemsByName('ID');
    var FindDuplicatesLikeParameter =
        GetSystemParameterValueEx('FindDuplicatesWithLike', true);
    if (FindDuplicatesLikeParameter) {
        var SummaryColumn = CreateCountSelectColumn(DuplicatesProperties,
            Select.Filters, Select.Columns,    FieldNames);
    } else {
        var SummaryColumn = AddSummaryColumn(Select.Columns, DuplicatesCode,
            SummaryTableField, stCount);
    }

    SummaryColumn.OrderType = otDesc;
    SummaryColumn.OrderPosition = 0;
    AddDuplicateFilters(DuplicatesProperties, Select, FieldNames);
    return CreatedQuery;   
}

function AddCountCompareFilters(ExpressionFilters, ParentFromTable,
    ParentFromTableAlias, SelectFromTable, SelectFromTableAlias,
    CheckFieldNames) {
    var CheckFieldName;
    for(var i = 0; i CheckFieldNames.length; i++) {
        CheckFieldName = CheckFieldNames[i];
        var FindDuplicatesLikeParameter =
            GetSystemParameterValueEx('FindDuplicatesWithLike', true);
        if (FindDuplicatesLikeParameter) {
            AddCountCompareFilterLike(ExpressionFilters, ParentFromTable,
                ParentFromTableAlias, SelectFromTable, SelectFromTableAlias,
                CheckFieldName);
        } else {
            AddCountCompareFilter(ExpressionFilters, ParentFromTable,
                ParentFromTableAlias, SelectFromTable, SelectFromTableAlias,
                CheckFieldName);
        }

    }
}

Вот и всё.

Нравится

Поделиться

5 комментариев

Доборый день :)

Получил ошибку при выполении:

var FindDuplicatesLikeParameter =            GetSystemParameterValueEx('FindDuplicatesWithLike', true);

"Ошибка выполнения метода 'wnd_SubjectDuplicatesOnPrepare'. Предполагается наличие объекта"

Параметр создал через Файл->Системные настройки. И в таблице tbl_SystemSettings он есть.

Подскажите, пожалуйста, в чем может быть проблема?
Версия: 3.1.0.16

Спасибо!

Думаю, какой- то скрипт не подключили. Например, scr_SystemSettings.

Не совсем :).

В версии 3.1.0 необходимо вызывать

var FindDuplicatesLikeParameter = GetSystemParameterValue('FindDuplicatesWithLike', sptBoolean);

вместо

var FindDuplicatesLikeParameter =            GetSystemParameterValueEx('FindDuplicatesWithLike', true);

Просто в скрипте scr_SystemSettings раньше не было функции GetSystemParameterValueEx.

Вообще доработка реализовывалась на версии 3.3.1, на более ранних версиях возможны проблемы.

Олег Лабьяк,
разработчик,
3-я линия Службы поддержки Terrasoft.

Олег, могу предложить тему для следующей записи в блоге - "нечеткий поиск" для поиска дублей :smile: Для справочников - мегаактуально.

Сергей, спасибо за предложение! Задача интересная, можно попробовать.

Олег Лабьяк,
разработчик,
3-я линия Службы поддержки Terrasoft.

Показать все комментарии