さくっと質問の回答をつくろうとしたら、エラーです。
Aggregate query does not support queryMore(), use LIMIT to restrict the results to a single batch
何で?えええええ。
調べたら解決策がありました。
#質問
https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000BdRF6SAN
#見直したプログラム
やっぱり、普通にアカウントから攻めた。
public class BAT_TowContactsOneAccount2 implements Database.Batchable<sObject> , Database.Stateful {
private Integer executeCount = 0;
private Integer Count = 0;
public BAT_TowContactsOneAccount2 () {
}
public Database.QueryLocator start(Database.BatchableContext BC) {
return Database.getQueryLocator(getTargetQuery());
}
public void execute(Database.BatchableContext BC, List<Account> scope) {
Savepoint sp = Database.setSavepoint();
try {
Count += scope.Size();
executeCount++;
List<Contact> insertContactList = new List<Contact>();
system.debug(Logginglevel.INFO,'====scope===========>>> '+ scope );
for (Account Acc : scope) {
system.debug(Logginglevel.INFO,'====Acc.Contacts.size()===========>>> '+ Acc.Contacts.size() );
If (Acc.Contacts.size() == 0) {
Contact c1 = new Contact();
c1.LastName = 'test2-1';
c1.FirstName = 'xx';
c1.AccountId = Acc.Id;
insertContactList.add(c1);
Contact c2 = new Contact();
c2.LastName = 'test2-2';
c2.FirstName = 'xx';
c2.AccountId = Acc.Id;
insertContactList.add(c2);
}
If (Acc.Contacts.size() == 1) {
Contact c1 = new Contact();
c1.LastName = 'test2-1';
c1.FirstName = 'xx';
c1.AccountId = Acc.Id;
insertContactList.add(c1);
}
}
if (insertContactList.size() >0) insert insertContactList;
}catch(Exception e) {
Database.rollback(sp);
} finally {
}
}
public void finish(Database.BatchableContext BC) {
System.debug('******** BAT_TowContactsOneAccount finish executeCount=' + executeCount + ', Count=' + Count);
}
private String getTargetQuery() {
String query = 'SELECT Id,(SELECT Id FROM Contacts) FROM Account ';
//system.debug(Logginglevel.INFO,'================>>>query '+ query );
return query;
}
}
#最初のプログラム
考え方:コンタクトの数を数えて、2より小さいもを対象にすればいいかな?
撃沈!!!
よく考えたらコンタクトが無いアカウントが抽出できん。あたりまえだな。
public class BAT_TowContactsOneAccount implements Database.Batchable<AggregateResult> , Database.Stateful {
private Integer executeCount = 0;
private Integer Count = 0;
public BAT_TowContactsOneAccount () {
}
public Iterable<AggregateResult> start(Database.BatchableContext BC){
System.debug('******** BAT_TowContactsOneAccount start');
String query = 'SELECT Count(Id),AccountId FROM Contact Group by AccountId HAVING COUNT(Id) < 2';
return new SearchResultIterable(query);
}
//public Database.QueryLocator start(Database.BatchableContext BC) {
//
// return Database.getQueryLocator(getTargetQuery());
//}
public void execute(Database.BatchableContext BC, List<AggregateResult> scope) {
Savepoint sp = Database.setSavepoint();
try {
Count += scope.Size();
executeCount++;
List<Contact> insertContactList = new List<Contact>();
system.debug(Logginglevel.INFO,'====scope===========>>> '+ scope );
for (AggregateResult AR : scope) {
If (AR.get('expr0') ==0) {
Contact c1 = new Contact();
c1.LastName = 'test2-1';
c1.FirstName = 'xx';
c1.AccountId = (Id)AR.get('AccountId');
insertContactList.add(c1);
Contact c2 = new Contact();
c2.LastName = 'test2-2';
c2.FirstName = 'xx';
c2.AccountId = (Id)AR.get('AccountId');
insertContactList.add(c2);
}
If (AR.get('expr0') ==1) {
Contact c1 = new Contact();
c1.LastName = 'test1';
c1.FirstName = 'xx';
c1.AccountId = (Id)AR.get('AccountId');
insertContactList.add(c1);
}
}
if (insertContactList.size() >0) insert insertContactList;
}catch(Exception e) {
Database.rollback(sp);
} finally {
}
}
public void finish(Database.BatchableContext BC) {
System.debug('******** BAT_TowContactsOneAccount finish executeCount=' + executeCount + ', Count=' + Count);
}
//private String getTargetQuery() {
// String query = 'SELECT Count(Id),AccountId FROM Contact Group by AccountId HAVING COUNT(Id) < 2 ';
// //system.debug(Logginglevel.INFO,'================>>>query '+ query );
// return query;
//}
public class SearchResultIterator Implements Iterator<AggregateResult>{
public AggregateResult [] results {get;set;}
public Integer index {get;set;}
public SearchResultIterator(String query){
this.index = 0;
results = Database.query(query);
}
public boolean hasNext(){
return results !=null && !results.isEmpty() && index < results.size();
}
public AggregateResult next(){
return results[index++];
}
}
public class SearchResultIterable implements Iterable<AggregateResult>{
private String query;
public SearchResultIterable(String soql){
this.query = soql;
}
public Iterator<AggregateResult> Iterator(){
return new SearchResultIterator(this.query);
}
}
}