1

Suppose i have 3 related objects: Continent - Country - City. Country object is child object of Continent and City is child object of Country. City -> Country -> Continent.

I would like make changes to a field on the continent object, based on a field on the city object. I want to use Batch Apex for this approach. So e.g. Say City has a field called ''Population''. If population on any city in any Country for a given Continent is more than 50.000.000, then a checkbox (Potential Customers) on Continent should change. But if the Continent does not have any Country with any City more than 50.000.000, then the checkbox should be/remain unchecked.

So, I understand that for this approach I cannot query downwards, going from parent to child object since we are going more than 1 level deep, hence it is necessary to query upwards, from child to parent. I imagine the query something like this:

global Database.QueryLocator start(Database.BatchableContext bc) {
    return Database.getQueryLocator([SELECT Id, Name, Population__c, Country__r.Id, Country__r.Continent__r.Id, Country__r.Continent.Potential_Customers__c FROM City__c]);
}

The execute method gives me trouble. I do not know how this should be done or how it can be done the smartest way. I am still learning Apex and SOQL. My suggestion would be using inner loops,

For(Continent)
    For(Country)
        For(City) 
if(Population > 5.000.000)
 Potential_Continent__c =  true

But again, I am not sure how i can do this programtically. And there are probably smarter ways to accomplish my problem above. Can anyone help?

2
  • 2
    Are the relationships between the three objects master-detail or lookup? What is the data volume for Country and City?
    – David Reed
    Commented Dec 31, 2019 at 15:15
  • Hi David, appreciate your reply. the relationships between the objects are lookup. City has lookup relationship to Country and Country has lookup to Continent. Data volume, I am not 100% sure. I expect somewhere between 100-200 records for Country. and maybe 500-1000 records for City, it could also be more. Commented Dec 31, 2019 at 16:16

1 Answer 1

1

I don't think you need a batch class for this. At the data volume you mentioned

I expect somewhere between 100-200 records for Country. and maybe 500-1000 records for City

you should be able to handle this with a couple of quick queries and run updates:

Map<Id, Continent__c> continentsToUpdate = new Map<Id, Continent__c>();

// First, find the Continents that need to have the flag set
for (City__c c: [SELECT Id, Country__r.Continent__c FROM City__c WHERE Population__c > 50000000]) {
    continentsToUpdate.put(
        c.Country__r.Continent__c,
        new Continent__c(Id = c.Country__r.Continent__c, Potential_Continent__c = true)
    );
}

// Now, find the Continents that have the wrong value for Potential Continent

for (Continent__c continent : [SELECT Id FROM Continent__c WHERE Potential_Continent__c = true AND Id NOT IN :continentsToUpdate.keySet()]) {
    continentsToUpdate.put(
        continent.Id,
        new Continent__c(Id = continent.Id, Potential_Continent__c = false)
    );
}

update continentsToUpdate.values();
1
  • Hi David, thanks for your detailed answer. There might be more records. I would like to stick to having the batch class. So i would need to have it in one query. Commented Jan 1, 2020 at 19:13

You must log in to answer this question.

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