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
PaulJSPaulJS 

SOQL query omitting duplicate values in trigger

I have a trigger in which I am assigning IDs to a list when the trigger is fired.  When I run a query against this list using WHERE ID IN:, the query does not return any duplicate values, which is causing a list index out of bounds error.

Here is my code for the assignment of the IDs to the initial list.

List<String> whatIDs = new List<String>();
   
    for (Task tk : Trigger.new){
       
        whatIDs.add(tk.whatID);
    }

And here is my code querying another object where the ID is found in that list.

List<Object1__c> oblist =  [SELECT ID, Name
                                                  FROM Object1__c
                                                  WHERE ID IN :whatIDs];

During testing, I had a list of 26 records in my initial list (whatIDs), but because my query is not returning duplicate values (there is one), I am only getting back 25 records.

Can anyone offer any suggestions/help?

Thanks.

-Paul
Best Answer chosen by PaulJS
Eli Flores, SFDC DevEli Flores, SFDC Dev
Use a map to remap the stuff... a Map<id, List<Task>> should do the trick

Map<id, List<Task>> obj1toTaskMap = new Map<id, List<Task>>();
for (Task tk : Trigger.new){
      List<Task> associatedTask  obj1toTaskMap.containsKey(tk.whatID) ? obj1toTaskMap.get(tk.whatID) : new List<Task>();
      associatedTask.add(tk);
      obj1toTaskMap.put(tk.whatID, associatedTasks); 
    }

List<Object1__c> oblist =  [SELECT ID, Name
                                                  FROM Object1__c
                                                  WHERE ID IN :obj1toTaskMap.keyset()];

then you run a double loop to process

for (Object1__c obj1 : oblist){
    for(Task tsk : obj1toTaskMap.get(obj1.id)) {
     //do stuff
    }
}

All Answers

Eli Flores, SFDC DevEli Flores, SFDC Dev
Use a map to remap the stuff... a Map<id, List<Task>> should do the trick

Map<id, List<Task>> obj1toTaskMap = new Map<id, List<Task>>();
for (Task tk : Trigger.new){
      List<Task> associatedTask  obj1toTaskMap.containsKey(tk.whatID) ? obj1toTaskMap.get(tk.whatID) : new List<Task>();
      associatedTask.add(tk);
      obj1toTaskMap.put(tk.whatID, associatedTasks); 
    }

List<Object1__c> oblist =  [SELECT ID, Name
                                                  FROM Object1__c
                                                  WHERE ID IN :obj1toTaskMap.keyset()];

then you run a double loop to process

for (Object1__c obj1 : oblist){
    for(Task tsk : obj1toTaskMap.get(obj1.id)) {
     //do stuff
    }
}
This was selected as the best answer
PaulJSPaulJS
Thanks Dev - that did it!  If you don't mind, could I ask you to explain a little further the line that starts "List<Task> associatedTask..."?  I can piece the rest of it together, but am trying to make sure I understand it for the future.
Eli Flores, SFDC DevEli Flores, SFDC Dev
Sure, That = .... ? ... : ...; is a short hand if then expression. The general form is like this Condition ? Truevalue : falsevalue. In the code the condition is the containsKey. If that's true, the expression evaluates to the map.get. If false, it evaluates to the new list. We are saying if the map contains the key get the value of the map else create a new list then assign it to the list variable. I find it more intuitive when assigning values to variables based I simple conditions. I would use if statements if the evaluation criteria were more complex. If my explanation was unclear, technically it's called the tertiary operator. If you google java tertiary operator, you'll probably get a better one.