• SFDC 在Batch Apex中使用Aggregate SOQL统计查询语句及结果


    在Batch Apex中使用Aggregate SOQL统计查询语句及结果


    前言

    Database.Batchable in Salesforce, but if you want to use SOQL having aggregate functions like SUM(), MAX(), COUNT() on results grouped by “GROUP BY” clause in start execution, changing to interface Database.Batchable isn’t a workable way, because it fails with the below compile error :

    Class must implement the global interface method: Iterable start(Database.BatchableContext) from Database.Batchable

    The following sample code will explain this.

    /*
     * Compile error : Class must implement the global interface method: Iterable<AggregateResult> start(Database.BatchableContext) from Database.Batchable<AggregateResult>
     */
    global class SampleAggregateBatch implements Database.Batchable<AggregateResult> {
      // The batch job starts
      global Database.Querylocator start(Database.BatchableContext bc){
        String query = 'SELECT COUNT(Id), AccountId FROM Contact GROUP BY AccountId';
        return Database.getQuerylocator(query);
      } 
      // The batch job executes and operates on one batch of records
      global void execute(Database.BatchableContext bc, List<sObject> scope){ }
      // The batch job finishes
      global void finish(Database.BatchableContext bc){ }
    }
    

    To fix this, using Apex classes that implement Iterator<AggregateResult> and Iterable<AggregateResult> seems the only way for now.

    Here is the outline what we should do.

    1. Create an Apex class implements Iterator<AggregateResult>.
    2. Create an Apex class implements Iterable<AggregateResult>.
    3. Implementing to Database.Batchable<AggregateResult>, and Using Iterable at start execution in Batch Apex.

    Let’s get started.

    Iterator Apex class

    Create an Apex class named “AggregateResultIterator” with the following source code :

    global class AggregateResultIterator implements Iterator<AggregateResult> {
      AggregateResult [] results {get;set;}
      // tracks which result item is returned
      Integer index {get; set;} 
           
      global AggregateResultIterator(String query) {
        index = 0;
        results = Database.query(query);            
      } 
    
      global boolean hasNext(){ 
        return results != null && !results.isEmpty() && index < results.size(); 
      }    
    
      global AggregateResult next(){        
        return results[index++];            
      }       
    }   
    

    Iterable Apex class

    Create an Apex class named “AggregateResultIterable” with the following source code :

    global class AggregateResultIterable implements Iterable<AggregateResult> {
      private String query;
    
      global AggregateResultIterable(String soql){
        query = soql;
      }
    
      global Iterator<AggregateResult> Iterator(){
        return new AggregateResultIterator(query);
      }
    }
    

    Batch Apex

    Then implement Batch Apex from Database.Batchable<AggregateResult>, and use Iterable<AggregateResult>, AggregateResultIterable instead of Database.QueryLocator at start execution, as the following source code :

    global class SampleAggregateBatch implements Database.Batchable<AggregateResult> {
      // The batch job starts
      global Iterable<AggregateResult> start(Database.BatchableContext bc){
        String query = 'SELECT COUNT(Id) cnt, AccountId FROM Contact GROUP BY AccountId';
        return new AggregateResultIterable(query);
      } 
      // The batch job executes and operates on one batch of records
      global void execute(Database.BatchableContext bc, List<sObject> scope){ 
        for(sObject sObj : scope) {
          AggregateResult ar = (AggregateResult)sObj;
          System.debug('>>>> COUNT : ' + ar.get('cnt'));
        }
      }
      // The batch job finishes
      global void finish(Database.BatchableContext bc){ }
    }
    

    Operation check

    Run SampleAggregateBatch and check debug log.

    // Run batch apex
    SampleAggregateBatch batch = new SampleAggregateBatch();
    Database.executebatch(batch, 200);
    
    // Debug log output
    11:36:35.0 (14518157)|USER_DEBUG|[11]|DEBUG|>>>> COUNT : 1
    11:36:35.0 (14903974)|USER_DEBUG|[11]|DEBUG|>>>> COUNT : 3
    11:36:35.0 (15035196)|USER_DEBUG|[11]|DEBUG|>>>> COUNT : 1
    

    It seems working fine! : )

    Enjoy it!

    Resource

    转载来源:https://www.xgeek.net/zh/salesforce/using-aggregate-soql-queries-results-in-batch-apex/

  • 相关阅读:
    在opencv3中实现机器学习之:利用正态贝叶斯分类
    在opencv3中进行图片人脸检测
    在opencv3中利用SVM进行图像目标检测和分类
    在opencv3中实现机器学习之:利用svm(支持向量机)分类
    在matlab和opencv中分别实现稀疏表示
    opencv2学习:计算协方差矩阵
    用python简单处理图片(3):添加水印
    Google protocol buffer在windows下的编译
    GEOS库学习之五:与GDAL/OGR结合使用
    GEOS库学习之四:几何关系判断
  • 原文地址:https://www.cnblogs.com/paynev/p/15129151.html
Copyright © 2020-2023  润新知