[SalesForce] Map Where Key is a different SObject

I'm trying to find a way to populate a Map<Id,List<SObject>> Where the key is an Id of a different SObject. Specifically, I'd like to return campaign members associated with contacts at an account with an Opportunity, and then use the AccountId as my map key. I'd then like to be able to sort that list based on a custom field value.

This thread here seems to be looking to do the same sort of thing, and I gather that I'll need to populate this Map myself with a loop. As a basic structure this probably looks something like this:

trigger CampaignMembers on Opportunity (after insert){
    Set<Id> accIds = new Set<Id>();

    for(Opportunity o : Trigger.new){
        accIds.add(o.AccountId);
    }

    Map<Id,List<CampaignMember>> accountCampaignMap = new Map<Id,List<CampaignMember>>();

    for(CampaignMember cm : [SELECT Id, CampaignId, AccountID_Formula__c FROM CampaignMember WHERE AccountID_Formula__c = :accIds]){
        //somehow populate Map
    }
    //do other stuff
}

This documentation also seems to suggest that if I need to create a wrapper class in order to support a custom sort, which I'd rather avoid, if possible.

To implement a custom sort order for sObjects in lists, create a
wrapper class for the sObject and implement the Comparable interface.
The wrapper class contains the sObject in question and implements the
compareTo method, in which you specify the sort logic.

Could I get around this by including an ORDER BY in my SOQL and then doing something like this:

for(CampaignMember cm : campaignMembers){
    if(accountCampaignMap.containsKey(cm.AccountID_Formula__c){
        accountCampaignMap.get(cm.AccountID_Formula__c).add(cm);
    }
    else{
        accountCampaignMap.put(cm.AccountID_Formula__c,cm);
    }
}

so that I'd be sorting it by default since my List that I'm looping through is already pre-sorted? Thanks in advance–it's been a long day…

Best Answer

A generic pattern for the sort of logic I think you are aiming to create is this:

for (CampaignMember cm : [
        SELECT Id, CampaignId, AccountID_Formula__c
        FROM CampaignMember
        WHERE AccountID_Formula__c = :accIds
        ORDER BY Name
        ]){
    List<CampaignMember> l = accountCampaignMap.get(cm.AccountID_Formula__c);
    if (l == null) {
        l = new List<CampaignMember>();
        accountCampaignMap.put(cm.AccountID_Formula__c, l);
    }
    l.add(cm);
}

This will result in each list being in the order of the CampaignMember.Name.

Related Topic