Salesforce Слишком много soql 101

#dictionary #salesforce #apex #soql

Вопрос:

  1. Это прекрасно работает в песочнице, но вызывает слишком много ошибок soql в производстве. Я пытался использовать 2. увеличенную карту со ссылкой на распространение контента с запросом soql, но она всегда блокировала объем на КАРТЕ. есть какие-нибудь советы ?
  2. Так как я перепробовал все с помощью списка CustomObject__c=[select… contentdistribution := ..id], но это также дает слишком много soql 101

@RestResource(сопоставление URL=’/API/V1/уведомление/*’) глобальный с общим классом API_Notice {

 @HttpGet(UrlMapping='/API/V1/notice/all')
global static List<String> getNotice(){          
    
    List<Object> senderJson = new List<Object>();  
    
    for (Notice__c a: [SELECT Name, ClosingDate__c,Contents__c, NoticeTypes__c,createddate,OfficialSenders__c,id,(SELECT ContentDocumentId  FROM ContentDocumentLinks) FROM Notice__c]) {               
            List<Object> multipleAcct = new List<Object>();                                       
            NoticeWrapper nw = new NoticeWrapper();
            Set<Id> contentsId = new Set<Id>();             
            List<Object> urls = new List<Object>();
            Set<Id> acctId = new Set<Id>();
        for(ContentDocumentLink cdl: a.ContentDocumentLinks){
            if(cdl.ContentDocumentId!=null){
                contentsId.add(cdl.ContentDocumentId);
             }
        }
        if(a.OfficialSenders__c != null){
            acctId.add(a.OfficialSenders__c);
        }
        
        if(a.id!=null){
            nw.noticeid = a.Id;               
       }     
        if(a.ClosingDate__c != null){   
            nw.ClosingDate = a.ClosingDate__c;                  
       }     
        if(a.NoticeTypes__c != null) {
            nw.NoticeTypes = a.NoticeTypes__c;                
        }    
        if(a.Contents__c !=null){
            nw.Contents = a.Contents__c;            
        }
        if(a.Name !=null) {
            nw.Name = a.Name;         
        }
        if(a.CreatedDate !=null){
            nw.createddate = a.createddate; 
        }  
        if(!acctId.isEmpty()){
             Map<Id,CampaignMember> camplinks = new Map<Id,CampaignMember>([
               select accountid ,CampaignId from CampaignMember where CampaignId IN: acctId 
            ]);                
            if(!camplinks.isEmpty()){
                for(CampaignMember cm : camplinks.values()){
                    multipleAcct.add(cm.AccountId);
                    nw.accountId = multipleAcct;  
                }
            }
        }
         if(!contentsId.isEmpty() amp;amp; contentsid!=null){
            Map<Id,ContentDistribution> links = new Map<Id,ContentDistribution>([
                select id , distributionPublicURL,ContentDocumentId from contentDistribution where ContentDocumentId IN: contentsId 
            ]); 
            if(!links.isEmpty()){
                for(contentDistribution cdb : links.values()){                          
                    urls.add(cdb.DistributionPublicUrl);
                    nw.DistributionPublicUrl = urls;
                    }
                }              
            }
    
       
        
                                          
        senderJson.add(nw);    
    }
    
    
   
        
    
        List<String> sends = new List<String>();

        for(Object json : senderJson){
            sends.add(String.valueof(json));
        }

        return sends;    
        
    }

@HttpPost
global static List<String> getOneNotice(String Id){
           
    List<Object> urls = new List<Object>();
    List<Object> senderJson = new List<Object>();
    List<Object> multipleAcct = new List<Object>();
    for (Notice__c a: [SELECT Name, ClosingDate__c,Contents__c,OfficialSenders__c, id,(SELECT ContentDocumentId FROM ContentDocumentLinks) FROM Notice__c where id=:id]) {
            Set<Id> acctId = new Set<Id>();
            Set<Id> contentsId = new Set<Id>();            
            NoticeWrapper nw = new NoticeWrapper();  
            nw.noticeid = a.Id;               
            nw.ClosingDate = a.ClosingDate__c;                
            nw.Contents = a.Contents__c;            
            nw.Name = a.Name;
        
                
            for(ContentDocumentLink cdl: a.ContentDocumentLinks){
                if(cdl.ContentDocumentId!=null){
                    contentsId.add(cdl.ContentDocumentId);
                }
            }
            if(a.OfficialSenders__c != null){
                acctId.add(a.OfficialSenders__c);
            }
        if(!acctId.isEmpty()){
             Map<Id,CampaignMember> camplinks = new Map<Id,CampaignMember>([
               select accountid ,CampaignId from CampaignMember where CampaignId IN: acctId 
            ]);
            
            if(!camplinks.isEmpty()){
                for(CampaignMember cm : camplinks.values()){
                    multipleAcct.add(cm.AccountId);
                    nw.accountId = multipleAcct;  
                }
            }
        }
        
        if(!contentsId.isEmpty()){
            Map<Id,ContentDistribution> links = new Map<Id,ContentDistribution>([
                select id , distributionPublicURL,ContentDocumentId from contentDistribution where ContentDocumentId IN: contentsId 
            ]);
        
        
        if(!links.isEmpty()){
                for(contentDistribution cdb : links.values()){
                    urls.add(cdb.DistributionPublicUrl);
                    nw.DistributionPublicUrl = urls;
                }
            }
        }
        senderJson.add(nw);    
    }                       
        List<String> sends = new List<String>();
      
        for(Object json : senderJson){
            sends.add(String.valueof(json));
    } 
    return sends;    
}
 

}

Ответ №1:

Контур вашей петли выглядит так

 for (Notice__c a: [SELECT Name, ClosingDate__c,Contents__c, NoticeTypes__c,createddate,OfficialSenders__c,id,(SELECT ContentDocumentId  FROM ContentDocumentLinks) FROM Notice__c]) {
    // ...
    if(!acctId.isEmpty()){
         Map<Id,CampaignMember> camplinks = new Map<Id,CampaignMember>([
           select accountid ,CampaignId from CampaignMember where CampaignId IN: acctId
        ]);
    }
    if(!contentsId.isEmpty() amp;amp; contentsid!=null){
        Map<Id,ContentDistribution> links = new Map<Id,ContentDistribution>([
            select id , distributionPublicURL,ContentDocumentId from contentDistribution where ContentDocumentId IN: contentsId
        ]);
    }
    // ...
    senderJson.add(nw);
}
 

Таким образом, это 2 запроса в каждой итерации цикла, он взорвется после 50 Notice__c записей. Возможно, вам удастся немного оптимизировать его, но скоро вы достигнете другого предела, например, 50 тысяч строк, запрашиваемых в одной транзакции. После того, как вам действительно понадобится некоторая оптимизация, возможно, подумайте о создании мини-объектов JSON, когда люди редактируют данные, и хранении их в вспомогательном текстовом поле внутри Notice__c ? Тогда API может просто запросить их готовность.

Проверьте, будет ли что — то подобное работать лучше.

 // 1. Query all notices.
// 2. Loop through them once to pull the Ids of related records we need to query.
// 3. Query the related stuff once and put it in a map we can easily access.
// 4. Then loop notices again, building the final JSON message.

// 1
List<Notice__c> notices = [SELECT Name, ClosingDate__c,Contents__c, NoticeTypes__c, createddate,
    OfficialSenders__c, id,
        (SELECT ContentDocumentId  FROM ContentDocumentLinks)
    FROM Notice__c];

Map<Id, Campaign> campaigns = new Map<Id, Campaign>();
Map<Id, ContentDocument> contentdocs = new Map<Id, ContentDocument>();

// 2
for (Notice__c a: notices){
    campaigns.put(a.OfficialSenders__c, null);
    for(ContentDocumentLink cdl: a.ContentDocumentLinks){
        contentdocs.put(cdl.ContentDocumentId, null);
    }
}
campaigns.remove(null); // who needs ifs in the loop if you can just remove them once afterwards
contentdocs.remove(null);

// 3a - Campaigns
if(!campaigns.isEmpty()){
    campaigns = new Map<Id, Campaign>([SELECT Id,
            (SELECT AccountId FROM CampaignMembers WHERE AccountId != null)
        FROM Campaign
        WHERE Id IN :campaigns.keyset()]);
}

// 3b - download links
if(!contentdocs.isEmpty()){
    contentdocs = new Map<Id, ContentDocument>([SELECT Id,
        (SELECT distributionPublicURL FROM ContentDistributions WHERE distributionPublicURL != null)
    FROM ContentDocument
    WHERE Id IN :contentdocs.keyset()]);
}

// 4
List<Object> senderJson = new List<Object>();
for (Notice__c a: notices){
    // bla bla, I'm skipping the ifs
    
    Id campaignId = a.OfficialSenders__c;
    // 4a
    if(campaigns.containsKey(campaignId)){
        Campaign c = campaigns.get(campaignId);
        Set<Id> accountIds = new Set<Id>();
        for(CampaignMember cm : c.CampaignMembers){
            accountIds.add(cm.AccountId);
        }
        // nw.accountId = accountIds;
    }
    
    // 4b
    if(!a.ContentDocumentLinks.isEmpty()){
        Set<String> urls = new Set<String>();
        for(ContentDocumentLink cdl: a.ContentDocumentLinks){
            Id cdi = cdl.ContentDocumentId;
            if(contentdocs.containsKey(cdi)){
                for(ContentDistribution cd : contentdocs.get(cdi).ContentDistributions){
                    urls.add(cd.distributionPublicURL);
                }
            }
        }
        // nw.DistributionPublicUrl = urls;
    }   
}
 

Комментарии:

1. Очень, очень ценю это , я пробовал таким образом, и это работает, спасибо