function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
CW5CW5 

How-To Query from Maps instead of FOR Loops to make BULK SAFE?

Essentially, all I'm trying to do is count the number of emails from a custom object that are related to the contact being updated and make it bulk safe (No errors when mass updating from the data loader).

 

The custom object is called "xtma_Individual_Email_Result__c" and contains individual emails that are sent with a related lookup containing the Contact ID.

 

I want to count 4 variables. How many emails related to that contact that were Sent (Has a Sent Date), Opened (Has an Opened Date), Clicked (Has at least 1 or more Unique Clicks), or Bounced (Has a Bounced Date).

 

I then want to put those 4 counts into 4 fields on the contact labeled appropriately.

 

This trigger works perfectly for a one-off update inside of SalesForce.com but provides the error "UpdateEmailCount: System.Exception: Too many script statements: 50001" when updated in mass (5,000+) through the dataloader.

 

My question is... How do I reprogram the FOR loops such as below, so that I don't hit the limits?

   

Integer numSent = 0; 

    for(Integer i = 0; i < lstcoa1.size(); i++) 
    { 
        if(lstcoa1[i].Contact__c == c.id) { 
        numSent = numSent + 1; 
        } 
    }    

 

 Is there a way to query from the Maps so that it counts all of the records in the map that match the Customer ID and the specific criteria (Such as Sent Date)?

 

 

 

Below is the full code:

 

trigger UpdateEmailCount on Contact (before update){

    Map<String, Contact> cobMap = new Map<String, Contact>();
    
    for (Contact cob : System.Trigger.New) {
            cobMap.put(cob.ID, cob);
    }

list<xtma_Individual_Email_Result__c> lstcoa1 = new list<xtma_Individual_Email_Result__c>();
list<xtma_Individual_Email_Result__c> lstcoa2 = new list<xtma_Individual_Email_Result__c> ();
list<xtma_Individual_Email_Result__c> lstcoa3 = new list<xtma_Individual_Email_Result__c> ();
list<xtma_Individual_Email_Result__c> lstcoa4 = new list<xtma_Individual_Email_Result__c> ();
 
 
for(xtma_Individual_Email_Result__c   obj : [SELECT Id, Contact__c,Date_Time_Sent__c,Date_Time_Opened__c,Number_of_Unique_Clicks__c,Date_Bounced__c
FROM xtma_Individual_Email_Result__c WHERE Contact__c IN :cobMap.KeySet()])
{  
  if(obj.Date_Time_Sent__c != null)
  {
  lstcoa1.add(obj);
  }
  if(obj.Date_Time_Opened__c != null)
  {
  lstcoa2.add(obj);
  }
  if(obj.Number_of_Unique_Clicks__c > 0)
  {
  lstcoa3.add(obj);
  }
  if(obj.Date_Bounced__c != null)
  {
  lstcoa4.add(obj);
  }
}

Map<ID, Integer> numSentMap = new Map<ID, Integer>();
Map<ID, Integer> numOpenedMap = new Map<ID, Integer>();
Map<ID, Integer> numClickedMap = new Map<ID, Integer>();
Map<ID, Integer> numBouncedMap = new Map<ID, Integer>();


for(Contact c: Trigger.New)
{
    Integer numSent = 0; 

    for(Integer i = 0; i < lstcoa1.size(); i++) 
    { 
        if(lstcoa1[i].Contact__c == c.id) { 
        numSent = numSent + 1; 
        } 
    }    

numSentMap.put(c.id,numSent);

}

for(Contact c: Trigger.New)
{
    Integer numOpened = 0; 


    for(Integer j = 0; j < lstcoa2.size(); j++) 
    { 
        if(lstcoa2[j].Contact__c == c.id) { 
        numOpened = numOpened + 1; 
        } 
    }
 
numOpenedMap.put(c.id,numOpened);

}

for(Contact c: Trigger.New)
{
    Integer numClicked = 0;  

    for(Integer k = 0; k < lstcoa3.size(); k++) 
    { 
        if(lstcoa3[k].Contact__c == c.id) { 
        numClicked = numClicked + 1; 
        } 
    }   

 
numClickedMap.put(c.id,numClicked);

}

for(Contact c: Trigger.New)
{
    Integer numBounced = 0; 


    for(Integer l = 0; l < lstcoa4.size(); l++) 
    { 
        if(lstcoa4[l].Contact__c == c.id) { 
        numBounced = numBounced + 1; 
        } 
    }
 
numBouncedMap.put(c.id,numBounced);

}
    
    for(Contact c: Trigger.New)
    {
    
         c.Number_Emails_Sent__c = numSentMap.get(c.id);
         c.Number_Emails_Opened__c = numOpenedMap.get(c.id);
         c.Number_Emails_Clicked__c = numClickedMap.get(c.id);
         c.Number_Emails_Bounced__c = numBouncedMap.get(c.id);
         
      }
    
}

 

CW5CW5

Wizrad helped me solve a problem with this new code. Here is all of it. However, it is still causing the TOO MANY STATEMENTS error. Does anyone have any ideas of how to reduce it even further or insight into why the trigger is causing this error?

 

Here is the latest version. It works on one-off updates but fails on bulk dataloader updates.

 

trigger UpdateEmailCount on Contact (before update){


    Map<String, Contact> cobMap = new Map<String, Contact>();
    
    for (Contact cob : System.Trigger.New) {
            cobMap.put(cob.ID, cob);
    }

list<xtma_Individual_Email_Result__c> lstcoa1 = new list<xtma_Individual_Email_Result__c>();
list<xtma_Individual_Email_Result__c> lstcoa2 = new list<xtma_Individual_Email_Result__c> ();
list<xtma_Individual_Email_Result__c> lstcoa3 = new list<xtma_Individual_Email_Result__c> ();
list<xtma_Individual_Email_Result__c> lstcoa4 = new list<xtma_Individual_Email_Result__c> ();
 
 
for(xtma_Individual_Email_Result__c   obj : [SELECT Id, Contact__c,Date_Time_Sent__c,Date_Time_Opened__c,Number_of_Unique_Clicks__c,Date_Bounced__c
FROM xtma_Individual_Email_Result__c WHERE Contact__c IN :cobMap.KeySet()])
{  
  if(obj.Date_Time_Sent__c != null)
  {
  lstcoa1.add(obj);
  }
  if(obj.Date_Time_Opened__c != null)
  {
  lstcoa2.add(obj);
  }
  if(obj.Number_of_Unique_Clicks__c > 0)
  {
  lstcoa3.add(obj);
  }
  if(obj.Date_Bounced__c != null)
  {
  lstcoa4.add(obj);
  }
}

Map<ID, Integer> numSentMap = new Map<ID, Integer>();
Map<ID, Integer> numOpenedMap = new Map<ID, Integer>();
Map<ID, Integer> numClickedMap = new Map<ID, Integer>();
Map<ID, Integer> numBouncedMap = new Map<ID, Integer>();


 Integer count;
 Integer first,second;
 if(lstcoa1.size()> lstcoa2.size())
 {
 first = lstcoa1.size();
 }
 else
 {
 first = lstcoa2.size();
 }
 if(lstcoa3.size() > lstcoa4.size())
 {
 second = lstcoa3.size();
 }
 else
 {
 second = lstcoa4.size();
 }
 if(first > second)
 {
 count = first;
 }
 else
 {
 count = second;
 
 }
 
 
 
 for(Contact c: Trigger.new)
 {
  Integer numSent = 0;
  Integer numOpened = 0;
  Integer numClicked = 0; 
  Integer numBounced = 0;
  for(Integer i = 0; i < count; i++)
  {
                
        if(i < lstcoa1.size() && lstcoa1[i].Contact__c == c.id)
        {
        numSent = numSent + 1;
        }
        
                
        if(i < lstcoa2.size() &&  lstcoa2[i].Contact__c == c.id) 
        {
        numOpened = numOpened + 1;
        }
        
        if(i < lstcoa3.size() && lstcoa3[i].Contact__c == c.id) 
        {
        numClicked = numClicked + 1;
        }
    
       
        if(i < lstcoa4.size() && lstcoa4[i].Contact__c == c.id) 
        {
        numBounced = numBounced + 1;
        }
  }
  
   //Adding records in Map
  numSentMap.put(c.id,numSent);
  numOpenedMap.put(c.id,numOpened);
  numClickedMap.put(c.id,numClicked);
  numBouncedMap.put(c.id,numBounced);
 
 
 }
    
    for(Contact c: Trigger.New)
    {
    
         c.Number_Emails_Sent__c = numSentMap.get(c.id);
         c.Number_Emails_Opened__c = numOpenedMap.get(c.id);
         c.Number_Emails_Clicked__c = numClickedMap.get(c.id);
         c.Number_Emails_Bounced__c = numBouncedMap.get(c.id);         
      }
    


}

 

 

WizradWizrad

Using the map like that defeats the purpose of using a Map.

 

Instead of having those nested loops youll want to do something similar to the following:

 

 for(Contact c: Trigger.new)
 {
  if(1stcoa1.contains(c.id)) numSentMap.put(c.id, numSentMap.get(c.id)++); 
 }
CW5CW5

Wizrad,

 

Thank you! Yes. Something like this is exactly what i'm looking for.

 

I'm getting the following error on that line.

Error: Compile Error: Expression cannot be assigned at line 47 column 71

 

I cleaned up the trigger and it looks like the following.

trigger UpdateEmailCount on Contact (before update){


    Map<String, Contact> cobMap = new Map<String, Contact>();
    
    for (Contact cob : System.Trigger.New) {
            cobMap.put(cob.ID, cob);
    }

list<xtma_Individual_Email_Result__c> lstcoa1 = new list<xtma_Individual_Email_Result__c>();
list<xtma_Individual_Email_Result__c> lstcoa2 = new list<xtma_Individual_Email_Result__c> ();
list<xtma_Individual_Email_Result__c> lstcoa3 = new list<xtma_Individual_Email_Result__c> ();
list<xtma_Individual_Email_Result__c> lstcoa4 = new list<xtma_Individual_Email_Result__c> ();
 
 
for(xtma_Individual_Email_Result__c   obj : [SELECT Id, Contact__c,Date_Time_Sent__c,Date_Time_Opened__c,Number_of_Unique_Clicks__c,Date_Bounced__c
FROM xtma_Individual_Email_Result__c WHERE Contact__c IN :cobMap.KeySet()])
{  
  if(obj.Date_Time_Sent__c != null)
  {
  lstcoa1.add(obj);
  }
  if(obj.Date_Time_Opened__c != null)
  {
  lstcoa2.add(obj);
  }
  if(obj.Number_of_Unique_Clicks__c > 0)
  {
  lstcoa3.add(obj);
  }
  if(obj.Date_Bounced__c != null)
  {
  lstcoa4.add(obj);
  }
}

Map<ID, Integer> numSentMap = new Map<ID, Integer>();
Map<ID, Integer> numOpenedMap = new Map<ID, Integer>();
Map<ID, Integer> numClickedMap = new Map<ID, Integer>();
Map<ID, Integer> numBouncedMap = new Map<ID, Integer>();


 Integer count;
 Integer first,second;
 if(lstcoa1.size()> lstcoa2.size())
 {
 first = lstcoa1.size();
 }
 else
 {
 first = lstcoa2.size();
 }
 if(lstcoa3.size() > lstcoa4.size())
 {
 second = lstcoa3.size();
 }
 else
 {
 second = lstcoa4.size();
 }
 if(first > second)
 {
 count = first;
 }
 else
 {
 count = second;
 
 }
 
 
 
 for(Contact c: Trigger.new)
 {
  Integer numSent = 0;
  Integer numOpened = 0;
  Integer numClicked = 0; 
  Integer numBounced = 0;
  for(Integer i = 0; i < count; i++)
  {
                
        if(i < lstcoa1.size() && lstcoa1[i].Contact__c == c.id)
        {
        numSent = numSent + 1;
        }
        
                
        if(i < lstcoa2.size() &&  lstcoa2[i].Contact__c == c.id) 
        {
        numOpened = numOpened + 1;
        }
        
        if(i < lstcoa3.size() && lstcoa3[i].Contact__c == c.id) 
        {
        numClicked = numClicked + 1;
        }
    
       
        if(i < lstcoa4.size() && lstcoa4[i].Contact__c == c.id) 
        {
        numBounced = numBounced + 1;
        }
  }
  
   //Adding records in Map
  numSentMap.put(c.id,numSent);
  numOpenedMap.put(c.id,numOpened);
  numClickedMap.put(c.id,numClicked);
  numBouncedMap.put(c.id,numBounced);
 
 
 }
    
    for(Contact c: Trigger.New)
    {
    
         c.Number_Emails_Sent__c = numSentMap.get(c.id);
         c.Number_Emails_Opened__c = numOpenedMap.get(c.id);
         c.Number_Emails_Clicked__c = numClickedMap.get(c.id);
         c.Number_Emails_Bounced__c = numBouncedMap.get(c.id);         
      }
    


}