Take the 2-minute tour ×
Salesforce Stack Exchange is a question and answer site for Salesforce administrators, implementation experts, developers and anybody in-between. It's 100% free, no registration required.

Is it possible to have a Map (or other collection) of sObjects list, keyed by one lookup field of the same sObject.

Something like Maps of sObjects (below code doesn't works):

Map<Id, List<Custom__c>> itemsMap = new Map<Id, List<Custom__c>>([SELECT Lookup_To_Custom__r.Id, Name FROM Custom__c]);

Note: this gives the following error Invalid initial type LIST<Custom__c> for MAP<Id,LIST<Custom__c>>

Where the Idin Map<Id, List<Custom__c>> is a reference to the Lookup_To_Custom__r.Id field.

share|improve this question

2 Answers 2

up vote 4 down vote accepted

The special map constructor only handles the case of creating a map where the key is the ID and the value is the SObject.

To do what I think you want to do requires a loop:

Map<Id, List<Custom__c>> m = new  Map<Id, List<Custom__c>>();
for (Custom__c c : [
        SELECT Lookup_To_Custom__c, Id, Name
        FROM Custom__c
        WHERE Lookup_To_Custom__c != null
        ORDER BY Name
        ]) {
    List<Custom__c> l = m.get(c.Lookup_To_Custom__c);
    if (l == null) {
        l = new List<Custom__c>();
        m.put(c.Lookup_To_Custom__c, l);
    }
    l.add(c);
}

Note that using the foreign key field Lookup_To_Custom__c is a little more direct than going through the reference and taking the ID Lookup_To_Custom__r.Id.

share|improve this answer

This is certainly possible. You just need to build the map yourself instead of trying to create it form a a single query.

As an example lets say we have a custom lookup on the contact record to another contact, say 'Emergency Contact'. Its possible that a person is listed as the emergency contact for more 1 person, so we could create a map where the key is the contact id, and the value is actually a list of contacts in which they are the emergency contact for.

Obviously this is a bit different from your case, but the same idea and you should easily be able to adjust the code for your scenario.

Map<Id, List<Contact>> conMap = new Map<Id, List<Contact>>();
for(Contact parent : [Select Id, Name, (Select Id, Name From EmergencyContacts__r) From Contact]) {
    conMap.put(parent.Id, new list<Contact>());
    for(Contact child : parent.EmergencyContacts__r){
         conMap.get(parent.Id).add(child);
    } 
}
system.debug('My Map: ' + conMap);

You now have a map where a contact Id is the key, and a list of contacts that person is the emergency contact for is the value.

Hope that helps

EDIT

Thinking about it more, you could likely make trim this down a bit more and just do this as well.

Map<Id, List<Contact>> conMap = new Map<Id, List<Contact>>();
for(Contact parent : [Select Id, Name, (Select Id, Name From EmergencyContacts) From Contact]) {
    conMap.put(parent.Id, parent.EmergencyContacts__r);
}

system.debug('My Map: ' + conMap);
share|improve this answer
    
I think the case in the question is a self-reference similar the Account.ParentId. –  Keith C Jul 31 at 17:56
    
My example is a self reference as well. I just didn't quite understand the use case and his example, which is why I did it in another context. Am i misunderstanding the question? –  sfdc_ninja Jul 31 at 17:59
    
Sorry I was put off by seeing Select Id, Name From EmergencyContacts rather than Select Id, Name From EmergencyContacts__r. Your solution is sneakier than mine :). –  Keith C Jul 31 at 18:03
    
Ahhhh, yes that was my mistake, good catch. Fixed that. Both our answers are right, just a bit of a different twist on each :) –  sfdc_ninja Jul 31 at 18:10
1  
+1 from me - getting the platform to do the work. –  Keith C Jul 31 at 18:12

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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