您在此处:
归档 Apex 数据查询
归档 Apex 数据查询支持以编程方式访问归档应用程序中的归档数据。这些数据查询自动化业务流程,支持第三方系统集成,创建自定义视图和报表,并将归档数据与有效记录进行交叉引用。
归档组件和归档搜索提供了手动数据检索的选项。Apex 提供高级功能,例如查询参数、筛选器和分页,以便通过代码直接访问数据。
Apex 数据查询功能包括:
- 使用指定条件搜索已归档记录。
- 使用带有星号 (*) 的部分匹配。
- 批量返回大型数据集,每页最多 1,000 个记录。
- 应用最多六个筛选器,以优化结果。
这些与系统相关的 Salesforce 对象被筛选出来,不能通过 Apex 搜索。
FeedHistoryRelationShare
为保持最佳性能并确保仅返回相关归档数据,归档会将这些对象从搜索中排除。
要访问已归档文件,请使用归档组件或归档搜索。
归档 Apex 数据查询方法
要定义如何查询已归档数据,请设置 Archive Apex 提供的方法。
- 访问归档数据 -
ArchiverAccessor中的方法旨在与归档记录交互。然后,您可以构建查询并检索存储在归档产品中的数据。 - 定义查询操作 - 这些签名告诉您使用 Apex 可以执行哪些类型的查询,例如全局搜索和筛选查询。
- 指导使用 — 通过检查方法签名,开发人员可以了解实施所需的输入和输出。
performArchiverGlobalSearch方法
此方法表示对已归档数据执行全局搜索的功能。
Query参数
Apex 数据查询使用几个参数来优化您的搜索。一些参数是必填项,而其他参数是可选项。了解如何配置每个参数有助于您获得最准确和相关的结果。
- 对象名称 — 指定要查询的 Salesforce 对象的类型。
例如,
string sObjectName = 'Account'指定查询的目标客户记录。此参数是必填项。
备注 每个查询针对一个对象。使用单独的查询从多个对象检索数据。 - 搜索筛选器 — 根据字段条件缩小搜索结果的筛选器。
- 字段名称 — 您要筛选的字段,例如
Name或CreatedDate - 值或值列表 — 要匹配的特定值
示例:单值筛选器
SF_Archive.SearchFilter filter = new SF_Archive.SearchFilter('Name', 'test');此查询返回名称字段匹配字符串“test”的记录。
示例:多值筛选器SF_Archive.SearchFilter filter = new SF_Archive.SearchFilter('Status', new List<String>{'Open', 'Closed'});此查询返回状态字段匹配字符串“未处理”或“已结束”的记录。
处理空或空值 — 要搜索字段为空或空的记录,您可以将空字符串 ("") 添加到值列表中。示例:
此查询返回主题字段为空或空的个案记录。List<SearchFilter> filters = new List<SearchFilter>(); filters.add(new SearchFilter('Subject', ''));搜索筛选器限制:
- 每个查询必须至少有一个筛选器。
- 每个查询最多可以有 6 个筛选器,与
AND逻辑相结合。 - 默认情况下,使用
AND逻辑组合筛选器。目前不支持OR逻辑。 - 筛选器的值列表不能超过 1000 个项目。
此参数是必填项。
- 字段名称 — 您要筛选的字段,例如
- 日期筛选器 — 如果要根据日期进行搜索,请使用
DateRange参数和强制筛选器。DateRange会按字段(例如ArchiveDate、CreatedDate或ModifiedDate)筛选记录。示例:特定日期查询的日期筛选器
Date todayDate = Date.today(); Date jan1st2024 = Date.newInstance(2024, 1, 1); DateRange dateRange = new DateRange('archive_date', jan1st2024, todayDate);此查询返回 2024 年 1 月 1 日至今天之间归档的记录。
示例:适用于多个日期范围的日期筛选器
List<SF_Archive.SearchFilter> filters = new List<SF_Archive.SearchFilter>(); SF_Archive.SearchFilter filter = new SF_Archive.SearchFilter('Name', 'test'); filters.add(filter); string sObjectName = 'Account'; Date myDate = Date.newInstance(2024, 1, 11); // January 11, 2024 Date myDate2 = Date.newInstance(2023, 12, 25); // December 12, 2023 SF_Archive.dateRange range = new SF_Archive.dateRange('CreatedDate', myDate, myDate); SF_Archive.dateRange range2 = new SF_Archive.dateRange('CreatedDate', myDate2, myDate2); list<SF_Archive.dateRange> ranges = new list<SF_Archive.dateRange> {range, range2}; SF_Archive.ArchiverAccessorResponse res = SF_Archive.ArchiverAccessor.performArchiverGlobalSearch(sObjectName, filters, ranges);此查询返回在 2023 年 12 月 12 日至 2024 年 1 月 11 日期间归档的记录。
日期筛选器建议:
- 要根据归档日期进行搜索,请添加
archive_date日期字段。 - 使用 Apex 日期格式:MM/DD/YYYY。
此参数是可选的。
- 要根据归档日期进行搜索,请添加
- 返回的字段 — 指定要包含在结果中的字段。如果未指定,将返回所有字段。
示例:返回特定字段
List<string> fields = new List<string>{'Name', 'CreatedDate'};此查询仅返回每个记录的
Name和CreatedDate字段。此参数是可选的。
- 页面大小 — 设置每个查询的记录数。每个查询的默认记录数是 25,最大值是 1000。
示例:自定义页面大小
SF_Archive.ArchiverAccessorResponse res = SF_Archive.ArchiverAccessor.performArchiverGlobalSearch('Account', filters, 100, fields);此查询返回每页 100 条记录。
此参数是可选的。备注 查询中超过 1000 条记录会触发运行时错误。 - 排序方向 — 按字段对结果进行排序,例如
CreatedDate。- 升序(
asc):最早到最新。 - 降序(
desc):最新到最旧。示例:排序查询
SortingDirection sortingDirection = new SortingDirection('desc');此查询返回根据
CreatedDate降序排序的记录。此参数是可选的。
- 升序(
getNextPage方法
如果结果不都适合同一页面,此方法会调用下一页。
ScrollId参数
通过获取最多 1000 条记录的页面结果,使用分页返回大型数据集。
要设置分页工作流,请执行初始查询,使用响应中的scrollId获取后续页面,并持续到scrollId = '-1'.。
示例:使用分页获取结果
// Perform initial search query
SF_Archive.ArchiverAccessorResponse res = SF_Archive.ArchiverAccessor.performArchiverGlobalSearch('Account',
filters, 100, fields);
// Get the search response
SF_Archive.ArchiverAccessorSearchResponse searchResponse = res.getSearchResponseMap();
// Process first page of results
system.debug('Total result count: ' + searchResponse.totalResultCount);
system.debug('Records: ' + searchResponse.records);
// Fetch next page using the scrollId
if (searchResponse.scrollId != '-1') {
SF_Archive.ArchiverAccessorResponse nextPageRes = SF_Archive.ArchiverAccessor.getNextPage(searchResponse.scrollId);
SF_Archive.ArchiverAccessorSearchResponse nextPageResponse = nextPageRes.getSearchResponseMap();
system.debug('Next Page Records: ' + nextPageResponse.records);
}访问方法
要查找方法签名,请转到“设置”下的 Apex 类。打开ArchiverAccessor类。查找 performArchiverGlobalSearch 命名空间下列出的所有方法。
示例数据查询
本示例使用这些条件检索Account记录。
- 字段:
Name、CreatedDate - 限制:每页 100 条记录
- 名称:包含字符串“test”
- 排序:按
CreatedDate降序
List<SF_Archive.SearchFilter> filters = new List<SF_Archive.SearchFilter>();
SF_Archive.SearchFilter filter = new SF_Archive.SearchFilter('Name', 'test');
filters.add(filter);
List<string> fields = new List<string>{'Name', 'CreatedDate'};
SortingDirection sortingDirection = new SortingDirection('desc');
SF_Archive.ArchiverAccessorResponse res = SF_Archive.ArchiverAccessor.performArchiverGlobalSearch('Account',
filters, 100, fields, sortingDirection);
排除常见错误
| 错误代码 | 描述 | 解决方案 |
|---|---|---|
INTERNAL_ERROR |
发生意外失败。 | 请联系支持,并提供错误详细信息。 |
RESOURCE_LIMIT_ERROR |
超出分页或查询大小限制。 | 减小页面大小或优化搜索筛选器。 |
VALIDATION_ERROR |
缺少或无效的搜索条件。 | 确保所有字段和筛选器有效。 |
其他推荐
- 监控 API 使用情况,以避免达到限制。
- 要将响应转换为对象,将其序列化为 JSON,然后反序列化回对象。
- 验证字段是否启用并可访问。
- 仔细检查所有查询参数。
- 对于未解决的问题,请联系 Salesforce 支持并提供详细日志。
有关逐步测试程序,请参见Archive Apex Testing。
- 归档 Apex 数据查询 — 代码示例
在此代码示例中,筛选器、日期范围和归档搜索请求通过归档应用程序中的状态代码进行验证。 - 归档 Apex 数据查询 — 用例 1 示例
此示例用例显示了如何构建和自定义在归档应用程序中显示高优先级客户的组件。 - 归档 Apex 数据查询 — 用例 2 示例
此示例用例显示了 Archive Apex 如何在归档应用程序中处理任务而不超出调控器限制,例如 CPU 限制或超时标注。
归档 Apex 数据查询 — 代码示例
在此代码示例中,筛选器、日期范围和归档搜索请求通过归档应用程序中的状态代码进行验证。
包含在(scrollId != -1)之后的getNextPage调用,因为结果的大小在performArchiverGlobalSearch调用中受到限制。
string sObjectName = 'Account';
list<SF_Archive.SearchFilter>request = new list<SF_Archive.SearchFilter>();
SF_Archive.SearchFilter filter1 = new SF_Archive.SearchFilter('Name', 'test');
request.add(filter1);
SF_Archive.dateRange range = new SF_Archive.dateRange('CreatedDate', system.today()-150, system.today());
SF_Archive.ArchiverAccessorResponse res = SF_Archive.ArchiverAccessor.performArchiverGlobalSearch(sObjectName, request, range);
if(res.getStatusCode() == 200){
system.debug('code: ' + res.getStatuscode());
SF_Archive.ArchiverAccessorSearchResponse searchResponse = res.getSearchResponseMap();
system.debug('count: '+ searchResponse.totalResultCount);
system.debug('scrollid: '+ searchResponse.scrollId);
system.debug('list size: '+ searchResponse.records.size());
string scrollId = searchResponse.scrollId;
integer page = 1;
while(scrollId != '-1'){
page++;
SF_Archive.ArchiverAccessorResponse secondPage =
SF_Archive.ArchiverAccessor.getNextPage(searchResponse.scrollId);
if(secondPage.getStatusCode() == 200){
SF_Archive.ArchiverAccessorSearchResponse searchResponse2 = secondPage.getSearchResponseMap();
scrollId = searchResponse2.scrollId;
system.debug('count: '+ searchResponse2.totalResultCount);
system.debug('scrollid: '+ searchResponse2.scrollId);
system.debug('list size: '+ searchResponse2.records.size());
system.debug('page number: '+ page);
} else{
system.debug('response is != 200: '+ secondPage.getStatusCode());
system.debug('body: '+ secondPage.getBody());
break;
}
}
} else {
system.debug('status code erorr|: '+ res.getStatusCode());
system.debug('status code message|: '+ res.getErrorMessage());
}归档 Apex 数据查询 — 用例 1 示例
此示例用例显示了如何构建和自定义在归档应用程序中显示高优先级客户的组件。
用例
您的业务要求 3 级支持团队有权查看具有高优先级状态的已归档个案。
此示例显示了如何:
- 创建自定义 Lightning Web 组件 (LWC)。
- 使用 Apex 数据查询提取归档数据。
- 应用筛选器(高优先级)。备注 其他筛选器可以通过引用归档 Apex 数据查询 - 代码示例中的代码进行自定义。
此示例限制为 25 条记录。Apex 允许您将结果设置为每页 1000 个。默认值为 25,带有通过结果分页的选项。
显示高优先级个案的组件
示例 SdkUseCaseWidget.js
在此代码示例中,参数是 AccountRecordId。
import { LightningElement, api, track } from 'lwc';
import getCases from '@salesforce/apex/ArchiveSdk.getCases';
export default class SampleSdkUseCaseWidget extends LightningElement {
@api recordId;
columns = [
{ label: 'Case Number', fieldName: 'caseNumber', type: 'text', cellAttributes: {alignment: 'center'}},
{ label: 'Subject', fieldName: 'subject', type: 'text' , cellAttributes: {alignment: 'center'}, },
{ label: 'Priority', fieldName: 'priority', type: 'text', cellAttributes: {alignment: 'center'}, },
{ label: 'Status', fieldName: 'status', type: 'text', cellAttributes: {alignment: 'center'}, }
];
@track records;
@track data
@track _loading;
async connectedCallback() {
this._loading = true;
try {
const result = await getCases({parentId: this.recordId})
this.records = result;
this._loading = false;
} catch (error) {
this._loading = false;
}}
} 示例 SdkUseCaseWidget.html
LWC 使用的 Apex 控制器调用 Apex 数据查询。
SF_Archive.ArchiverAccessor.performArchiverGlobalSearch(sObjectName, request, fields, range);这是对 Archive Apex 的调用。它包括这些参数。
- sObjectName — 描述搜索
- 筛选器 — 用于检索数据
- 字段 — 从数据返回的预计字段。
- 范围 — 用于查询数据的日期范围。
<template>
<template if:true={_loading}>
<lightning-spinner></lightning-spinner>
</template>
<lightning-datatable
key-field="caseNumber"
data={records}
columns={columns}
hide-checkbox-column>
</lightning-datatable>
</template>ArchiveSdk.cls
此代码块是 Apex 控制器。
public with sharing class ArchiveSDK {
@AuraEnabled
public static List<CaseTableWrapperExample.CaseRecord> getCases(String parentId) {
// Create an empty list to hold maps with String keys and Object values
List<Map<String, Object>> totalRecords = new List<Map<String, Object>>();
// Create a list to store search filter objects
List<SF_Archive.SearchFilter> request = new List<SF_Archive.SearchFilter>();
// Create a search filter for the 'AccountId' field with a given 'parentId' value
SF_Archive.SearchFilter filter1 = new SF_Archive.SearchFilter('AccountId', parentId);
// Create a search filter for the 'Priority' field with a given 'High' value
SF_Archive.SearchFilter filter2 = new SF_Archive.SearchFilter('Priority', 'High');
// Add the filters to the request list
request.add(filter1);
request.add(filter2);
// Define the object name as 'Case'
String sObjectName = 'Case';
// Create a list of Strings representing field names to be retrieved from Archive DB
List<String> fields = new List<String>{'CaseNumber', 'Subject', 'Priority', 'Status'};
// Create the DateRange based on the created date
SF_Archive.DateRange range = new SF_Archive.DateRange('CreatedDate', system.today() - 150, system.today());
// Perform an initial global search and store the response
SF_Archive.ArchiverAccessorResponse res = SF_Archive.ArchiverAccessor.performArchiverGlobalSearch(sObjectName, request, range);
// Check if the HTTP response status code is 200 (success)
if (res.getStatusCode() == 200) {
system.debug('code: ' + res.getStatuscode());
// Retrieve the initial search response map
SF_Archive.ArchiverAccessorSearchResponse searchResponse = res.getSearchResponseMap();
system.debug('count: ' + searchResponse.totalResultCount);
system.debug('scrollid: ' + searchResponse.scrollId);
system.debug('list size: ' + searchResponse.records.size());
// Store the scroll ID for pagination
String scrollId = searchResponse.scrollId;
// Initialize the page number
Integer page = 1;
// Add the records from the initial search to the totalRecords list
totalRecords.addAll(searchResponse.records);
// Continue to fetch additional pages while the scroll ID is not '-1'
while (scrollId != '-1') {
page++;
// Get the next page of search results using the UPDATED scrollId
SF_Archive.ArchiverAccessorResponse nextPageResponse = SF_Archive.ArchiverAccessor.getNextPage(scrollId);
// Check if the HTTP response status code is 200 (success)
if (nextPageResponse.getStatusCode() == 200) {
// Retrieve the search response for the current page
SF_Archive.ArchiverAccessorSearchResponse searchResponse2 = nextPageResponse.getSearchResponseMap();
// CRITICAL FIX: Update the scrollId with the value from the new response
scrollId = searchResponse2.scrollId;
system.debug('count: ' + searchResponse2.totalResultCount);
system.debug('scrollid: ' + searchResponse2.scrollId);
system.debug('list size: ' + searchResponse2.records.size());
system.debug('page number: ' + page);
// Add the records from the current page to the totalRecords list
totalRecords.addAll(searchResponse2.records);
} else {
// Output an error message if the HTTP response status code is not 200
system.debug('response is != 200: ' + nextPageResponse.getStatusCode());
system.debug('body: ' + nextPageResponse.getBody());
// Break out of the loop if there is an error
break;
}
} // End of while loop
} else {
// Handle error from initial search
system.debug('status code error: ' + res.getStatusCode());
system.debug('status code message: ' + res.getErrorMessage());
}
// Return the list of total records
List<CaseTableWrapperExample.CaseRecord> result = new List<CaseTableWrapperExample.CaseRecord>();
return CaseTableWrapperExample.getCasesTable(totalRecords);
}
}CaseTableWrapperExample.cls
从 Apex 到 LWC 制定类的助手类
public class CaseTableWrapperExample{
public static List<caseRecord> getCasesTable(list<map<string,object>> cases){
List<caseRecord> caseReturnList = new List<caseRecord>();
for(Map<string,object> caseRecord: cases){
caseRecord tempCase = new caseRecord();
tempCase.caseNumber = String.valueOf(caseRecord.get('CaseNumber'));
tempCase.id = String.valueOf(caseRecord.get('Id'));
tempCase.origin = String.valueOf(caseRecord.get('Origin'));
tempCase.status = String.valueOf(caseRecord.get('Status'));
tempCase.subject = String.valueOf(caseRecord.get('Subject'));
tempCase.priority = String.valueOf(caseRecord.get('Priority'));
caseReturnList.add(tempCase);
}
return caseReturnList;
}
public class caseRecord {
@AuraEnabled public string caseNumber;
@AuraEnabled public string id;
@AuraEnabled public string origin;
@AuraEnabled public string status;
@AuraEnabled public string priority;
@AuraEnabled public string subject;
}}以上代码描述了一个示例场景,您可以将 LWC 作为组件添加到 Lightning 页面。
要查看实际 Lightning 数据表,将此代码添加到sampleSdkUseCaseWidget.js-meta.xml文件中。然后将归档组件添加到 Lightning 页面。
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="<a href='http://soap.sforce.com/2006/04/metadata">;
<apiVersion>55.0</apiVersion>
<isExposed>true</isExposed>
<targets>
<target>lightning__RecordPage</target>
<target>lightning__AppPage</target>
</targets>
<targetConfigs>
<targetConfig targets="lightning__RecordPage">
<supportedFormFactors>
<supportedFormFactor type="Small" />
<supportedFormFactor type="Large" />
</supportedFormFactors>
</targetConfig>
<targetConfig targets="lightning__AppPage">
<supportedFormFactors>
<supportedFormFactor type="Small" />
<supportedFormFactor type="Large" />
</supportedFormFactors>
</targetConfig>
</targetConfigs>
</LightningComponentBundle>归档 Apex 数据查询 — 用例 2 示例
此示例用例显示了 Archive Apex 如何在归档应用程序中处理任务而不超出调控器限制,例如 CPU 限制或超时标注。
有关更多信息,请查看Apex 调控器限制。
用例
您的业务要求 3 级支持团队有权查看具有高优先级状态的已归档个案。
此示例显示了当通过 Apex 检索的归档记录数量过大时,如何处理错误。错误如下:SF_Archive.ArchiverAccessor.ArchiverAccessorException: Exceeded time
allotted for callout, please contact support.
这些 Apex 类中的代码会创建此用例。
ArchiveSecondPageJob 类通过使用滚动 ID 处理归档中的分页数据,并根据需要进行标注。它通过可排队界面异步运行,跟踪总执行时间以避免超出限制,并在需要时将自己排队等待继续处理。该类处理响应,更新滚动 ID,并记录每个检索到的数据页面的详细信息。
public class ArchiveSecondPageJob implements Queueable,Database.AllowsCallouts {
private String scrollId;
private long totalTime;
private integer pageNumber;
public archiveSecondPageJob(String prevScrollId, integer pageNumber) {
scrollId = prevScrollId;
this.pageNumber = pageNumber;
}
public void execute(QueueableContext context) {
system.debug('executing');
doExecute();
}
private void doExecute() {
SF_Archive.ArchiverAccessorSearchResponse searchResponse = null;
integer page = 1;
long totalTime = 0;
while(scrollId != '-1')
{
//avoid 12000 ms limit
if(totalTime > 90000){
system.debug('Creating new task');
archiveSecondPageJob q = new archiveSecondPageJob(scrollId,this.pageNumber);
System.enqueueJob(q);
return;
}
//Get the next page using the scrollId
Long startTime = DateTime.now().getTime();
SF_Archive.ArchiverAccessorResponse nextPage = SF_Archive.ArchiverAccessor.getNextPage(scrollId);
Long stopTime = DateTime.now().getTime();
totalTime += stopTime - startTime;
if(nextPage.getStatusCode() == 200){
this.pageNumber++;
SF_Archive.ArchiverAccessorSearchResponse searchResponse2 =nextPage.getSearchResponseMap();
scrollId = searchResponse2.scrollId;
system.debug('count: '+ searchResponse2.totalResultCount);
system.debug('scrollid: '+ searchResponse2.scrollId);
system.debug('list size: '+ searchResponse2.records.size());
system.debug('body: '+ searchResponse2.records);
system.debug('page: '+ pageNumber);
system.debug('time: '+ totalTime);
}
else{
system.debug('response is != 200: '+ nextPage.getStatusCode());
system.debug('body: '+ nextPage.getBody());
return;
}
}
}
}
ArchiveSearch 类通过使用特定筛选器对个案对象执行搜索,检索结果,并记录详细信息,例如总数和滚动 ID。如果搜索返回有效的滚动 ID,指示结果的更多页面,它会将异步处理下一页的archiveSecondPageJob排队。该类基本上启动搜索,并将进一步处理移交给之前定义的archiveSecondPageJob。
以下是初始搜索调用的格式。
public class ArchiveSearch {
public void doSearch(){
string sObjectName = 'Case';
list<SF_Archive.SearchFilter> request = new list<SF_Archive.SearchFilter>();
SF_Archive.SearchFilter filter1 = new SF_Archive.SearchFilter('Priority', 'High');
request.add(filter1);
list<string> fields = new list<string>{'CaseNumber', 'Id'};
SF_Archive.ArchiverAccessorResponse res = SF_Archive.ArchiverAccessor.performArchiverGlobalSearch(sObjectName, request, fields);
if(res.getStatusCode() == 200){
system.debug('code: ' + res.getStatuscode());
SF_Archive.ArchiverAccessorSearchResponse searchResponse = res.getSearchResponseMap();
system.debug('count: '+ searchResponse.totalResultCount);
system.debug('scrollid: '+ searchResponse.scrollId);
system.debug('list size: '+ searchResponse.records.size());
string scrollId = searchResponse.scrollId;
integer page = 1;
if(scrollId != '-1'){
system.debug('calling next page');
integer pageNumber = 2;
archiveSecondPageJob q = new archiveSecondPageJob(scrollId, pageNumber);
System.enqueueJob(q);
}}}}有关更多信息,请参阅Salesforce Apex 开发人员指南。

