You need to sign in to do that
Don't have an account?
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); } }
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.
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:
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.