2

I've got the following query:

List<Order> orders = [SELECT Id, (SELECT Id, Type_Reference__c FROM Cases__r) FROM Order WHERE Id IN :orderIds];

and I need to store that information in the following map:

List<Id, Map<String,List<Case>>> orderToCaseMap = new List<Id, Map<String,List<Case>>>();

So, essentially, storing Order Id in the Id, Type_Reference__c in the String key, and the case list in the List<Case> value.

The business scenario, (just in case there is a better way of doing this): Whenever a case is created and linked to an order, we populate a picklist value on the case (Type Reference) - if a case with that specific type reference already exists, we don't wanna create a duplicate case

So far I have tried

List<Id, Map<String,List<Case>>> orderToCaseMapping = new List<Id, Map<String,List<Case>>>();
Map<String, List<Case>> caseMap = new Map<String, List<Case>>();
List<Case> caseList = new List<Case>();

        for (Order ord : orderList) {
            for (Case cs : ord.Cases__r) {
                caseList.add(cs);
                caseMap.put(cs.Type_Reference__c, caseList);
            }
            orderToCaseMapping.put(ord.Id, caseMap); // not sure about this part
        }

But it's ugly as heck and won't compile

2
  • What you have tried so far? Where you have stuck? May 28 '20 at 9:25
  • 1
    I edited my post
    – erikvm
    May 28 '20 at 9:30
2

Here it went wrong

Problem #1

List<Id, Map<String,List<Case>>> orderToCaseMap = new List<Id, Map<String,List<Case>>>();

It Should be a map of ( id, map of (String, list of cases)), like below:

Map<Id, Map<String,List<Case>>> orderToCaseMapping = new Map<Id, Map<String,List<Case>>>();

Problem #2 You are not initializing a new List<Case> (or cloning and clearing) for each iteration of the loop over Order. This would cause all Orders to contain all Cases (instead of just the Cases related to a given Order).

Problem #3 You need to initialize the new map Map<String, List<Case>> for each order.

Resolving all those issues, the final code will be like below.

Map<Id, Map<String,List<Case>>> orderToCaseMapping = new Map<Id, Map<String,List<Case>>>();
for (Order ord : orders) {
    Map<String, List<Case>> caseMap = new Map<String, List<Case>>();
    for (Case cs : ord.Cases__r) {
        if(String.isNotBlank(cs.Type_Reference__c)){
            if(!caseMap.containsKey(cs.Type_Reference__c)){
                caseMap.put(cs.Type_Reference__c, new List<Case>());
            }
            caseMap.get(cs.Type_Reference__c).add(cs);
        }
    }
    orderToCaseMapping.put(ord.Id, caseMap);
}

Please mind that the keySet of the map is case sensitive.

4
  • 1
    The other missteps in OP's original code are 1) Not initializing a new List<Case> (or cloning and clearing) for each iteration of the loop over Order. 2) Calling put() inside the inner loop over Case. #2 isn't s big problem, just a waste of resources. #1, however, would cause all Orders to contain all Cases (instead of just the Cases related to a given Order). The code in this answer does address both of those.
    – Derek F
    May 28 '20 at 11:37
  • @DerekF Thanks for pointing out, I couldn't figure out how to mention that in words. I will update this in my answer. May 28 '20 at 11:43
  • Thanks a lot guys! I guess you can't have an outer <List> type..
    – erikvm
    May 29 '20 at 9:17
  • 1
    @erikvm you can have, but list can have only one argument like List<Type> but you were trying List<Type, Type2>. but this works with the map: Map<Type, Type2>. Also both the type can be the same as well. May 29 '20 at 9:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.