1

Hi Im kind of stucked here, What Im trying to do is getting a Map which for each key (Id) will have a set of related objects.

Map<Id, Set<Id>> junctMap = new Map<Id, Set<Id>>([SELECT Id, (SELECT Id FROM Equipment_Maintenance_Items__r) FROM Case WHERE Id IN:idSet]);

Bu it keeps throwing me "Invalid initializer type List found for Map>: Expected a Map, with the same key and value types.

Do you know if my approach is valid or I'm doing it all wrong?

I would like to know, what am I doing wrong.

3 Answers 3

1

You can't do this with a single statement in Apex.

Queries always return a List<SObject>, and there is a constructor for the Map class that can take a List<SObject> and turn it into a Map<Id, SObject>. Anything that you want to do beyond that requires additional code.

Further, Apex will complain that there are too many child records if there are more than ~200 children for a given parent and you try to directly access the embedded List<SObject>. That'll try to kick off an internal call to queryMore(), and that's not allowed for fetching the child records.

The safest way to access the child records is with a nested loop.

for(Parent__c parentRec :parentList){
    system.debug(parentRec.Id);

    for(Child__c childRec :parentRec.Child_Relationship__r){
        system.debug(childRec.Id);
    }
}

So you'll need to build your Map<Id, Set<Id>> yourself, using the nested loop approach. You can:

  • Create a new Set<Id> in the outer loop (before the inner loop runs)
  • Add Ids to the set in the inner loop
  • myMap.put(parentId, childIdSet) in the outer loop (before or after the inner loop runs)

Having Set<Id> mySet = new Set<Id>(); inside of the outer loop ensures that your map will only store the child Ids for the given parent. If you'd define this set outside of all loops, you'd end up needing to do extra work to prevent cross-polination of child ids (and to avoid clearing out all ids).

1
  • Thank you, your answer along with what @joacoiudica said, clarified me a lot. "Queries always return a List<SObject>." Thanks Jul 12, 2022 at 17:18
3

You can only use Map<Id, sObject> (and concrete subtypes, like Account or AggregateResult) when using the Map<T, U>(inlineQuery) constructor. For your use case, you'd have to initialize the Map, then loop over the results:

Map<Id, Set<Id>> junctMap = new Map<Id, Set<Id>>();
for(Case record: [SELECT (SELECT Id FROM Equipment_Maintenance_Items__r) FROM Case WHERE Id = :idSet]) {
  Set<Id> tempIds = new Set<Id>();
  junctMap.put(record.Id, tempIds);
  for(Equipment_Maintenance_Item__c item: record.Equipment_Maintenance_Items__r) {
    tempIds.add(item.Id);
  }
}
1
  • Solution included here, so I'm upvoting this. Jul 12, 2022 at 16:58
1

You can't do that directly. if you check the Map class documentation, the only way you can initialize a map directly with SOQL is if you define a Map<Id, sObject> where the sObject is the one you are querying against. To accomplish what you want, you have to loop through the results of the query and subquery to fill the map and inner sets.

You must log in to answer this question.

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