Как заменить вложенный цикл for на Map и каким-либо образом сократить время расчета части? - PullRequest
0 голосов
/ 06 июня 2019

Как заменить вложенный цикл for на карту?

КАК ЗАМЕНИТЬ ВСТРОЕННОЕ ДЛЯ LOOP ПО КАРТЕ

публичный класс Casecal {public void verifytime (List caseids, Map casemap) {

    map<string,List<CaseMilestone>> milestonemap = new map<string,List<CaseMilestone>>();
    if(casemap!=null && caseids.size()>0){
        BusinessHours bh = [SELECT Id FROM BusinessHours WHERE IsDefault=true];
        List<Case> caselist = [Select id, (select caseId,id,isCompleted,MilestoneTypeId,BusinessHoursId,MilestoneType.name,CompletionDate from 
                                           CaseMilestones where(MilestoneType.name='First Response' or MilestoneType.name='Technical Resolution')
                                           AND caseid IN:casemap.keySet()) from case]; 

        for(Case cs: caselist ){
            milestonemap.put(cs.id,cs.Casemilestones);
        }
        for(Case c: caseids){
            if(c.Request_for_Closure_Date__c!=null && milestonemap.containskey(c.id) ){
                for(CaseMilestone ml:milestonemap.get(c.id)){
                    if(ml.MilestoneType.name=='First Response'){
                        Integer ms = Integer.valueOf((BusinessHours.diff(bh.id, ml.CompletionDate, c.Request_for_Closure_Date__c))/1000);
                        system.debug('Time@calculation'+ms);
                        Integer sec = ms;
                        Integer mns = sec/60;
                        integer days = mns / 60 / 24 ;
                        integer hours = (mns - days * 60 * 24) / 60 ;
                        integer mins = mns - days * 60 * 24 - hours * 60 ;
                        String timeSpentOnCase = days+'Days '+hours+'Hours '+mins+'Minutes'+sec+'Secs';
                        System.debug('Time'+timeSpentOnCase);

                        c.Test_Ignore__c = ml.CompletionDate;
                    }
                    else if(ml.MilestoneType.name=='Technical Resolution'){
                        c.Test_Ignore_2__c = ml.CompletionDate;
                    }
                }
            }
        }
    }
}

}

Ответы [ 2 ]

1 голос
/ 06 июня 2019

Как сказал Дэвид в вышеприведенном комментарии, доступ довольно оптимизирован, как есть. Если вы ищете дополнительную оптимизацию, я бы:

  • Переместите if(c.Request_for_Closure_Date__c!=null и улучшите предложение WHERE (почему вы хотите получить некоторые Случаи, если пропустите их при обработке?). Так что-то вроде

    SELECT Id,
        (SELECT CaseId, Id, isCompleted...
        FROM CaseMilestones
        WHERE ...)
    FROM Case
    WHEREId IN :caseids AND Request_for_Closure_Date__c!=null    
    
  • выбросить этот код. Если это только для system.debug - вы просто тратите время на вычисления.

    Integer ms = Integer.valueOf((BusinessHours.diff(bh.id, ml.CompletionDate, c.Request_for_Closure_Date__c))/1000);
    system.debug('Time@calculation'+ms);
    Integer sec = ms;
    Integer mns = sec/60;
    integer days = mns / 60 / 24 ;
    integer hours = (mns - days * 60 * 24) / 60 ;
    integer mins = mns - days * 60 * 24 - hours * 60 ;
    String timeSpentOnCase = days+'Days '+hours+'Hours '+mins+'Minutes'+sec+'Secs';
    System.debug('Time'+timeSpentOnCase);
    

Если после этих двух оптимизаций у вас все еще есть проблемы с производительностью, вам, возможно, придется пересмотреть свою бизнес-логику и запрос. Гарантируется ли, что в каждом случае будет не более 1 этапа каждого типа?

Может быть, вам нужен подзапрос только с одним типом, который даст вам последний этап? Что-то вроде SELECT Id, (SELECT CompletionDate FROM CaseMilestones WHERE Type = 'x' ORDER BY CompletionDate DESC LIMIT 1) FROM Case? Затем вы запускаете этот запрос для второго типа и процесса. Хорошо, тратит впустую 2 запроса, но гарантированно возвращает только несколько строк.

Или, может быть, вы можете полностью упростить этот код, выполнив что-то вроде

SELECT CaseId, MAX(CompletionDate) d, MilestoneType.Name t
FROM CaseMilestone
WHERE CaseId IN :... AND MilestoneType.Name IN :...
GROUP BY CaseId, MilestoneType.Name
1 голос
/ 06 июня 2019

Эти циклы уже оптимизированы, но доступ к данным на основе карты фактически не требуется, поскольку дочерние объекты запрашиваются родителями.

    for(Case cs: caselist ){
        milestonemap.put(cs.id,cs.Casemilestones);
    }

Это совсем не нужно и может быть удалено. Вместо этого измените внутренний цикл for, чтобы он напрямую ссылался на дочерний список CaseMilestones.

    for(Case c: caseids){
        if(c.Request_for_Closure_Date__c!=null){
            for(CaseMilestone ml : c.CaseMilestones){

Цикл просто не будет выполняться, если c.CaseMilestones пусто.

Для этого кода дальнейшая оптимизация на основе карты не предусмотрена.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...