3

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>>

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

2 Answers 2

5

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.

4

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);
6
  • I think the case in the question is a self-reference similar the Account.ParentId.
    – Keith C
    Jul 31, 2014 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? Jul 31, 2014 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, 2014 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 :) Jul 31, 2014 at 18:10
  • I'm really struggling to accept an answer, I think I'm going with @KeithC 's answer, since his practically worked on copy - paste for my use case (I think I could have elaborated a bit more), but thank both of you.
    – Jose
    Jul 31, 2014 at 18:24

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .