SOQL
Apex Classes: SOQL.cls and SOQL_Test.cls.
The lib main class for query construction.
SOQL.of(Account.SObjectType)
.with(Account.Id, Account.Name)
.toList();
Methods​
The following are methods for using SOQL:
with(SObjectField field)with(SObjectField field1, SObjectField field2)with(SObjectField field1, SObjectField field2, SObjectField field3)with(SObjectField field1, SObjectField field2, SObjectField field3, SObjectField field4)with(SObjectField field1, SObjectField field2, SObjectField field3, SObjectField field4, SObjectField field5)with(List<SObjectField> fields)with(List<String> fields)with(String fields)with(String relationshipName, SObjectField field)with(String relationshipName, SObjectField field1, SObjectField field2)with(String relationshipName, SObjectField field1, SObjectField field2, SObjectField field3)with(String relationshipName, SObjectField field1, SObjectField field2, SObjectField field3, SObjectField field4)with(String relationshipName, SObjectField field1, SObjectField field2, SObjectField field3, SObjectField field4, SObjectField field5)with(String relationshipName, Iterable<SObjectField> fields)withFieldSet(String fieldSetName)
count()count(SObjectField field)count(SObjectField field, String alias)count(String relationshipName, SObjectField field)count(String relationshipName, SObjectField field, String alias)avg(SObjectField field)avg(SObjectField field, String alias)avg(String relationshipName, SObjectField field)avg(String relationshipName, SObjectField field, String alias)countDistinct(SObjectField field)countDistinct(SObjectField field, String alias)countDistinct(String relationshipName, SObjectField field)countDistinct(String relationshipName, SObjectField field, String alias)min(SObjectField field)min(SObjectField field, String alias)min(String relationshipName, SObjectField field)min(String relationshipName, SObjectField field)max(SObjectField field)max(SObjectField field, String alias)max(String relationshipName, SObjectField field)max(String relationshipName, SObjectField field, String alias)sum(SObjectField field)sum(SObjectField field, String alias)sum(String relationshipName, SObjectField field)sum(String relationshipName, SObjectField field, String alias)
toLabel(SObjectField field)toLabel(SObjectField field, String alias)toLabel(String field)toLabel(String field, String alias)
delegatedScope()mineScope()mineAndMyGroupsScope()myTerritoryScope()myTeamTerritoryScope()teamScope()
whereAre(FilterGroup filterGroup)whereAre(Filter filter)whereAre(String dynamicCondition)conditionLogic(String order)anyConditionMatching();
groupBy(SObjectField field)groupBy(String relationshipName, SObjectField field)groupByRollup(SObjectField field)groupByRollup(String relationshipName, SObjectField field)groupByCube(SObjectField field)groupByCube(String relationshipName, SObjectField field)
have(HavingFilterGroup filterGroup)have(HavingFilter filter)have(String dynamicCondition)havingConditionLogic(String order)anyHavingConditionMatching()
orderBy(SObjectField field)orderBy(String field)orderBy(String field, String direction)orderBy(String relationshipName, SObjectField field)orderByCount(SObjectField field)sordDesc()sort(String direction)nullsLast()nullsOrder(String nullsOrder)
mockId(String id)SOQL.mock(String mockId).thenReturn(SObject record)SOQL.mock(String mockId).thenReturn(List<SObject> records)SOQL.mock(String mockId).thenReturn(Integer amount)SOQL.mock(SObjectType ofObject).thenReturn(SObject record)SOQL.mock(SObjectType ofObject).thenReturn(List<SObject> records)SOQL.mock(SObjectType ofObject).thenReturn(Integer amount)SOQL.mock(String mockId).throwException()SOQL.mock(String mockId).throwException(String message)
byId(SObject record)byId(Id recordId)byIds(Iterable<Id> recordIds)byIds(List<SObject> records)byRecordType(String recordTypeDeveloperName)
toId()toIds()toIdsOf(SObjectField field)toIdsOf(String relationshipName, SObjectField field)doExist()toValueOf(SObjectField fieldToExtract)toValuesOf(SObjectField fieldToExtract)toInteger()toObject()toList()toAggregated()toMap()toMap(SObjectField keyField)toMap(String relationshipName, SObjectField targetKeyField)toMap(SObjectField keyField, SObjectField valueField)toAggregatedMap(SObjectField keyField)toAggregatedMap(String relationshipName, SObjectField targetKeyField)toAggregatedMap(SObjectField keyField, SObjectField valueField)toIdMapBy(SObjectField field)toIdMapBy(String relationshipName, SObjectField targetKeyField)toAggregatedIdMapBy(SObjectField keyField)toAggregatedIdMapBy(String relationshipName, SObjectField targetKeyField)toQueryLocator()toCursor()toPaginationCursor()
INIT​
of​
Constructs an SOQL.
Signature
Queryable of(SObjectType ofObject)
Queryable of(String ofObject)
Example
SELECT Id FROM Account
SOQL.of(Account.SObjectType).toList();
SOQL.of('Account').toList();
SELECT​
with field1 - field5​
Signature
Queryable with(SObjectField field)
Queryable with(SObjectField field1, SObjectField field2);
Queryable with(SObjectField field1, SObjectField field2, SObjectField field3);
Queryable with(SObjectField field1, SObjectField field2, SObjectField field3, SObjectField field4);
Queryable with(SObjectField field1, SObjectField field2, SObjectField field3, SObjectField field4, SObjectField field5);
Example
SELECT Id, Name
FROM Account
SOQL.of(Account.SObjectType)
.with(Account.Id, Account.Name)
.toList();
// or
SOQL.of(Account.SObjectType)
.with(Account.Id)
.with(Account.Name)
.toList();
with fields​
SELECTstatement that specifies the fields to query. The fieldList in theSELECTstatement specifies the list of one or more fields, separated by commas, that you want to retrieve.
Use for more than 5 fields.
Signature
Queryable with(List<SObjectField> fields)
Queryable with(List<String> fields)
Example
SELECT Id, Name, Industry, AccountNumber, AnnualRevenue, BillingCity
FROM Account
SOQL.of(Account.SObjectType)
.with(new List<SObjectField>{
Account.Id,
Account.Name,
Account.Industry,
Account.AccountNumber,
Account.AnnualRevenue,
Account.BillingCity
}).toList();
SOQL.of(Account.SObjectType)
.with(new List<String>{
'Id',
'Name',
'Industry',
'AccountNumber',
'AnnualRevenue',
'BillingCity'
}).toList();
with string fields​
NOTE! With String Apex does not create reference to field. Use SObjectField whenever it possible. Method below should be only use for dynamic queries.
Signature
Queryable with(String fields)
Example
SELECT Id, Name, Industry
FROM Account
SOQL.of(Account.SObjectType)
.with('Id, Name, Industry')
.toList();
with related field1 - field5​
Allows to add parent field to a query.
Signature
Queryable with(String relationshipName, SObjectField field)
Queryable with(String relationshipName, SObjectField field1, SObjectField field2);
Queryable with(String relationshipName, SObjectField field1, SObjectField field2, SObjectField field3);
Queryable with(String relationshipName, SObjectField field1, SObjectField field2, SObjectField field3, SObjectField field4);
Queryable with(String relationshipName, SObjectField field1, SObjectField field2, SObjectField field3, SObjectField field4, SObjectField field5);
Example
SELECT CreatedBy.Name
FROM Account
SOQL.of(Account.SObjectType)
.with('CreatedBy', User.Name)
.toList();
SOQL.of(Account.SObjectType)
.with('CreatedBy', User.Id, User.Name, User.Phone)
.toList();
with related fields​
Allows to add parent fields to a query.
Use for more than 5 parent fields.
Signature
Queryable with(String relationshipName, Iterable<SObjectField> fields)
Example
SELECT
CreatedBy.Id,
CreatedBy.Name,
CreatedBy.Phone,
CreatedBy.FirstName,
CreatedBy.LastName,
CreatedBy.Email
FROM Account
SOQL.of(Account.SObjectType)
.with('CreatedBy', new List<SObjectField>{
User.Id,
User.Name,
User.Phone,
User.FirstName,
User.LastName,
User.Email
}).toList();
with field set​
Pass FieldSet name to get dynamic fields.
Signature
Queryable withFieldSet(String fieldSetName)
Example
SELECT
Id,
Name,
Industry
FROM Account
SOQL.of(Account.SObjectType)
.withFieldSet('AccountFieldSet')
.toList();
SUB-QUERY​
with subquery​
Use SOQL to query several relationship types.
For more details check SOQL.SubQuery class.
Signature
Queryable with(SOQL.SubQuery subQuery)
Example
SELECT Id, (
SELECT Id, Name
FROM Contacts
) FROM Account
SOQL.of(Account.SObjectType)
.with(SOQL.SubQuery.of('Contacts')
.with(Contact.Id, Contact.Name)
).toList();
AGGREGATE FUNCTIONS​
Note! To avoid the Field must be grouped or aggregated error, any default fields that are neither in Aggregation Functions nor included in the GROUP BY clause will be automatically removed.
count​
COUNT()returns the number of rows that match the filtering conditions.
Note! COUNT() must be the only element in the SELECT list, any other fields will be automatically removed.
Signature
Queryable count()
Example
SELECT COUNT()
FROM Account
SOQL.of(Account.SObjectType).toInteger();
// or
SOQL.of(Account.SObjectType)
.count()
.toInteger();
count field​
Signature
count(SObjectField field)
Note! To avoid the Field must be grouped or aggregated error, any default fields will be automatically removed.
You can still specify additional fields, but they should be placed after the COUNT() function in the SELECT statement.
Example
SELECT COUNT(Id), COUNT(CampaignId)
FROM Opportunity
SOQL.of(Opportunity.SObjectType)
.count(Opportunity.Id)
.count(Opportunity.CampaignId)
.toAggregated();
count with alias​
Signature
Queryable count(SObjectField field, String alias)
Example
SELECT COUNT(Name) names FROM Account
SOQL.of(Account.SObjectType)
.count(Account.Name, 'names')
.toAggregated();
count related field​
Signature
count(String relationshipName, SObjectField field)
Example
SELECT COUNT(Account.Name) FROM Contact
SOQL.of(Contact.SObjectType)
.count('Account', Account.Name)
.toAggregated();
count related field with alias​
Signature
Queryable count(String relationshipName, SObjectField field, String alias)
Example
SELECT COUNT(Account.Name) names FROM Contact
SOQL.of(Contact.SObjectType)
.count('Account', Account.Name, 'names')
.toAggregated();
avg​
Signature
Queryable avg(SObjectField field)
Example
SELECT CampaignId, AVG(Amount) FROM Opportunity GROUP BY CampaignId
SOQL.of(Opportunity.SObjectType)
.with(Opportunity.CampaignId)
.avg(Opportunity.Amount)
.groupBy(Opportunity.CampaignId)
.toAggregate();
avg with alias​
Signature
Queryable avg(SObjectField field, String alias)
Example
SELECT CampaignId, AVG(Amount) amount FROM Opportunity GROUP BY CampaignId
SOQL.of(Opportunity.SObjectType)
.with(Opportunity.CampaignId)
.avg(Opportunity.Amount, 'amount')
.groupBy(Opportunity.CampaignId)
.toAggregate();
avg related field​
Signature
avg(String relationshipName, SObjectField field)
Example
SELECT AVG(Opportunity.Amount) FROM OpportunityLineItem
SOQL.of(OpportunityLineItem.SObjectType)
.avg('Opportunity', Opportunity.Amount)
.toAggregate();
avg related field with alias​
Signature
Queryable avg(String relationshipName, SObjectField field, String alias)
Example
SELECT AVG(Opportunity.Amount) amount FROM OpportunityLineItem
SOQL.of(OpportunityLineItem.SObjectType)
.avg('Opportunity', Opportunity.Amount, 'amount')
.toAggregate();
count_distinct​
Signature
Queryable countDistinct(SObjectField field
Example
SELECT COUNT_DISTINCT(Company) FROM Lead
SOQL.of(Lead.SObjectType)
.countDistinct(Lead.Company)
.toAggregate();
count_distinct with alias​
Signature
Queryable countDistinct(SObjectField field, String alias)
Example
SELECT COUNT_DISTINCT(Company) company FROM Lead
SOQL.of(Lead.SObjectType)
.countDistinct(Lead.Company, 'company')
.toAggregate();
count_distinct related field​
Signature
Queryable countDistinct(String relationshipName, SObjectField field)
Example
SELECT COUNT_DISTINCT(Lead.Company) FROM CampaignMember
SOQL.of(CampaignMember.SObjectType)
.countDistinct('Lead', Lead.Company)
.toAggregate();
count_distinct related field with aliast​
Signature
Queryable countDistinct(String relationshipName, SObjectField field, String alias)
Example
SELECT COUNT_DISTINCT(Lead.Company) company FROM CampaignMember
SOQL.of(CampaignMember.SObjectType)
.countDistinct('Lead', Lead.Company, 'company')
.toAggregate();
min​
Signature
Queryable min(SObjectField field)
Example
SELECT FirstName, LastName, MIN(CreatedDate)
FROM Contact
GROUP BY FirstName, LastName
SOQL.of(Contact.SObjectType)
.with(Contact.FirstName, Contact.LastName)
.min(Contact.CreatedDate)
.groupBy(Contact.FirstName)
.groupBy(Contact.LastName)
.toAggregate();
min with alias​
Signature
Queryable min(SObjectField field, String alias)
Example
SELECT FirstName, LastName, MIN(CreatedDate) createDate
FROM Contact
GROUP BY FirstName, LastName
SOQL.of(Contact.SObjectType)
.with(Contact.FirstName, Contact.LastName)
.min(Contact.CreatedDate, 'createDate')
.groupBy(Contact.FirstName)
.groupBy(Contact.LastName)
.toAggregate();
min related field​
Signature
Queryable min(String relationshipName, SObjectField field)
Example
SELECT MIN(Account.CreatedDate) FROM Contact
SOQL.of(Contact.SObjectType)
.min('Account', Account.CreatedDate)
.toAggregate();
min related field with alias​
Signature
Queryable min(String relationshipName, SObjectField field, String alias)
Example
SELECT MIN(Account.CreatedDate) createdDate FROM Contact
SOQL.of(Contact.SObjectType)
.min('Account', Account.CreatedDate, 'createdDate')
.toAggregate();
max​
Signature
Queryable max(SObjectField field)
Example
SELECT Name, MAX(BudgetedCost)
FROM Campaign
GROUP BY Name
SOQL.of(Campaign.SObjectType)
.with(Campaign.Name)
.max(Campaign.BudgetedCost)
.groupBy(Campaign.Name)
.toAggregate();
max with alias​
Signature
Queryable max(SObjectField field, String alias)
Example
SELECT Name, MAX(BudgetedCost) budgetedCost
FROM Campaign
GROUP BY Name
SOQL.of(Campaign.SObjectType)
.with(Campaign.Name)
.max(Campaign.BudgetedCost, 'budgetedCost')
.groupBy(Campaign.Name)
.toAggregate();
max related field​
Signature
Queryable max(String relationshipName, SObjectField field)
Example
SELECT MAX(Campaign.BudgetedCost) FROM CampaignMember
SOQL.of(CampaignMember.SObjectType)
.max('Campaign', Campaign.BudgetedCost)
.toAggregate();
max related field with alias​
Signature
Queryable max(String relationshipName, SObjectField field, String alias)
Example
SELECT MAX(Campaign.BudgetedCost) budgetedCost FROM CampaignMember
SOQL.of(CampaignMember.SObjectType)
.max('Campaign', Campaign.BudgetedCost, 'budgetedCost')
.toAggregate();
sum​
Signature
Queryable sum(SObjectField field)
Example
SELECT SUM(Amount) FROM Opportunity
SOQL.of(Opportunity.SObjectType)
.sum(Opportunity.Amount)
.toAggregate();
sum with alias​
Signature
Queryable sum(SObjectField field, String alias)
Example
SELECT SUM(Amount) amount FROM Opportunity
SOQL.of(Opportunity.SObjectType)
.sum(Opportunity.Amount, 'amount')
.toAggregate();
GROUPING​
grouping​
Signature
Queryable grouping(SObjectField field, String alias)
Example
SELECT LeadSource, Rating,
GROUPING(LeadSource) grpLS, GROUPING(Rating) grpRating,
COUNT(Name) cnt
FROM Lead
GROUP BY ROLLUP(LeadSource, Rating)
SOQL.of(Lead.SObjectType)
.with(Lead.LeadSource, Lead.Rating)
.grouping(Lead.LeadSource, 'grpLS')
.grouping(Lead.Rating, 'grpRating')
.count(Lead.Name, 'cnt')
.groupByRollup(Lead.LeadSource)
.groupByRollup(Lead.Rating)
.toAggregated();
sum related field​
Signature
sum(String relationshipName, SObjectField field)
Example
SELECT SUM(Opportunity.Amount) FROM OpportunityLineItem
SOQL.of(OpportunityLineItem.SObjectType)
.sum('Opportunity', Opportunity.Amount)
.toAggregate();
sum related field with alias​
Signature
Queryable sum(String relationshipName, SObjectField field, String alias)
Example
SELECT SUM(Opportunity.Amount) amount FROM OpportunityLineItem
SOQL.of(OpportunityLineItem.SObjectType)
.sum('Opportunity', Opportunity.Amount, 'amount')
.toAggregate();
toLabel​
To translate SOQL query results into the language of the user who submits the query, use the toLabel method.
Signature
Queryable toLabel(SObjectField field)
Queryable toLabel(SObjectField field, String alias)
Queryable toLabel(String field)
Queryable toLabel(String field, String alias)
Example
SELECT Company, toLabel(Status) FROM Lead
SOQL.of(Lead.SObjectType)
.with(Lead.Company)
.toLabel(Lead.Status)
.toList();
SELECT Company, toLabel(Status) leadStatus FROM Lead
SOQL.of(Lead.SObjectType)
.with(Lead.Company)
.toLabel(Lead.Status, 'leadStatus')
.toList();
SELECT Company, toLabel(Recordtype.Name) FROM Lead
SOQL.of(Lead.SObjectType)
.with(Lead.Company)
.toLabel('Recordtype.Name')
.toList();
SELECT Company, toLabel(Recordtype.Name) recordTypeName FROM Lead
SOQL.of(Lead.SObjectType)
.with(Lead.Company)
.toLabel('Recordtype.Name', 'recordTypeName')
.toList();
format​
Signature
format(SObjectField field)
format(SObjectField field, String alias)
Example
SELECT FORMAT(Amount) FROM Opportunity
SOQL.of(Opportunity.SObjectType)
.format(Opportunity.Amount)
.toList();
SELECT FORMAT(Amount) amt FROM Opportunity
SOQL.of(Opportunity.SObjectType)
.format(Opportunity.Amount, 'amt')
.toList();
USING SCOPE​
delegatedScope​
Filter for records delegated to another user for action. For example, a query could filter for only delegated Task records.
Signature
Queryable delegatedScope()
Example
SELECT Id
FROM Task
USING SCOPE DELEGATED
SOQL.of(Task.SObjectType)
.delegatedScope()
.toList();
mineScope​
Filter for records owned by the user running the query.
Signature
Queryable mineScope()
Example
SELECT Id
FROM Account
USING SCOPE MINE
SOQL.of(Account.SObjectType)
.mineScope()
.toList();
mineAndMyGroupsScope​
Filter for records assigned to the user running the query and the user’s queues. If a user is assigned to a queue, the user can access records in the queue. This filter applies only to the ProcessInstanceWorkItem object.
Signature
Queryable mineAndMyGroupsScope()
Example
SELECT Id
FROM ProcessInstanceWorkItem
USING SCOPE MINE_AND_MY_GROUPS
SOQL.of(ProcessInstanceWorkItem.SObjectType)
.mineAndMyGroupsScope()
.toList();
myTerritoryScope​
Filter for records in the territory of the user running the query. This option is available if territory management is enabled for your organization.
Signature
Queryable myTerritoryScope()
Example
SELECT Id
FROM Opportunity
USING SCOPE MY_TERRITORY
SOQL.of(Opportunity.SObjectType)
.myTerritoryScope()
.toList();
myTeamTerritoryScope​
Filter for records in the territory of the team of the user running the query. This option is available if territory management is enabled for your organization.
Signature
Queryable myTeamTerritoryScope()
Example
SELECT Id
FROM Opportunity
USING SCOPE MY_TEAM_TERRITORY
SOQL.of(Opportunity.SObjectType)
.myTeamTerritoryScope()
.toList();
teamScope​
Filter for records assigned to a team, such as an Account team.
Signature
Queryable teamScope()
Example
SELECT Id FROM Account USING SCOPE TEAM
SOQL.of(Account.SObjectType)
.teamScope()
.toList();
WHERE​
whereAre​
The condition expression in a
WHEREclause of a SOQL query includes one or more field expressions. You can specify multiple field expressions in a condition expression by using logical operators.
For more details check SOQL.FilterGroup and SOQL.Filter
Signature
Queryable whereAre(FilterClause conditions)
Example
SELECT Id
FROM Account
WHERE Id = :accountId OR Name = '%MyAccount%'
SOQL.of(Account.SObjectType)
.whereAre(SOQL.FilterGroup
.add(SOQL.Filter.with(Account.Id).equal(accountId))
.add(SOQL.Filter.with(Account.Name).contains('MyAccount'))
.anyConditionMatching()
).toList();
whereAre string​
Execute conditions passed as String.
Signature
Queryable whereAre(String conditions)
Example
SELECT Id
FROM Account
WHERE NumberOfEmployees >=10 AND NumberOfEmployees <= 20
SOQL.of(Account.SObjectType)
.whereAre('NumberOfEmployees >=10 AND NumberOfEmployees <= 20')
.toList();
conditionLogic​
Set conditions order for SOQL query. When not specify all conditions will be with AND.
Signature
Queryable conditionLogic(String order)
Example
SELECT Id
FROM Account
WHERE Name = 'Test' AND BillingCity = 'Krakow'
SOQL.of(Account.SObjectType)
.whereAre(SOQL.Filter.with(Account.Name).equal('Test'))
.whereAre(SOQL.Filter.with(Account.BillingCity).equal('Krakow'))
.conditionLogic('1 OR 2')
.toList();
anyConditionMatching​
When the conditionLogic is not specified, all conditions are joined using the AND operator by default.
To change the default condition logic, you can utilize the anyConditionMatching method, which joins conditions using the OR operator.
Signature
Queryable anyConditionMatching()
Example
SELECT Id
FROM Account
WHERE Name = 'Test' AND BillingCity = 'Krakow'
SOQL.of(Account.SObjectType)
.whereAre(SOQL.Filter.with(Account.Name).equal('Test'))
.whereAre(SOQL.Filter.with(Account.BillingCity).equal('Krakow'))
.anyConditionMatching()
.toList();
GROUP BY​
groupBy​
You can use the
GROUP BYoption in a SOQL query to avoid iterating through individual query results. That is, you specify a group of records instead of processing many individual records.
Signature
Queryable groupBy(SObjectField field)
Example
SELECT LeadSource
FROM Lead
GROUP BY LeadSource
SOQL.of(Lead.SObjectType)
.with(Lead.LeadSource)
.groupBy(Lead.LeadSource)
.toAggregated();
groupBy related​
Signature
Queryable groupBy(String relationshipName, SObjectField field)
Example
SELECT COUNT(Name) count
FROM OpportunityLineItem
GROUP BY OpportunityLineItem.Opportunity.Account.Id
SOQL.of(OpportunityLineItem.SObjectType)
.count(OpportunityLineItem.Name, 'count')
.groupBy('OpportunityLineItem.Opportunity.Account', Account.Id)
.toAggregated();
groupByRollup​
Signature
Queryable groupByRollup(SObjectField field)
Example
SELECT LeadSource, COUNT(Name) cnt
FROM Lead
GROUP BY ROLLUP(LeadSource)
SOQL.of(Lead.SObjectType)
.with(Lead.LeadSource)
.count(Lead.Name, 'cnt')
.groupByRollup(Lead.LeadSource)
.toAggregated();
groupByRollup related​
Signature
Queryable groupByRollup(String relationshipName, SObjectField field)
Example
SELECT COUNT(Name) cnt
FROM Lead
GROUP BY ROLLUP(ConvertedOpportunity.StageName)
SOQL.of(Lead.SObjectType)
.count(Lead.Name, 'cnt')
.groupByRollup('ConvertedOpportunity', Opportunity.StageName)
.toAggregated();
groupByCube​
Signature
Queryable groupByCube(SObjectField field)
Example
SELECT Type
FROM Account
GROUP BY CUBE(Type)
SOQL.of(Account.SObjectType)
.with(Account.Type)
.groupByCube(Account.Type)
.toAggregated();
groupByCube related​
Signature
Queryable groupByCube(String relationshipName, SObjectField field)
Example
SELECT COUNT(Name) cnt
FROM Lead
GROUP BY CUBE(ConvertedOpportunity.StageName)
SOQL.of(Lead.SObjectType)
.count(Lead.Name, 'cnt')
.groupByCube('ConvertedOpportunity', Opportunity.StageName)
.toAggregated();
WITH DATA_CATEGORY​
For more details check SOQL.DataCategoryFilter.
Signature
Queryable withDataCategory(DataCategoryFilter dataCategoryFilter);
Example
SELECT Id, Title
FROM Knowledge__kav
WITH DATA CATEGORY Geography__c AT (Europe__c, North_America__c)
SOQL.of(Knowledge__kav.SObjectType)
.with(Knowledge__kav.Id, Knowledge__kav.Title)
.withDataCategory(SOQL.DataCategoryFilter.with('Geography__c').at(new List<String>{ 'Europe__c', 'North_America__c' }))
.toList();
HAVING​
have​
HAVINGis an optional clause that can be used in a SOQL query to filter results that aggregate functions return.
For more details check SOQL.HavingFilterGroup and SOQL.HavingFilter
Signature
Queryable have(HavingFilterGroup havingFilterGroup)
Queryable have(HavingFilter havingFilter)
Example
SELECT LeadSource, COUNT(Name)
FROM Lead
GROUP BY LeadSource, City
HAVING COUNT(Name) > 100 AND City LIKE 'San%'
SOQL.of(Lead.SObjectType)
.with(Lead.LeadSource)
.count(Lead.Name)
.groupBy(Lead.LeadSource)
.groupBy(Lead.City)
.have(SOQL.HavingFilter.count(Lead.Name).greaterThan(100))
.have(SOQL.HavingFilter.with(Lead.City).startsWith('San'))
.toAggregated();
having string​
Execute having conditions passed as String.
Signature
Queryable have(String conditions)
Example
SELECT LeadSource, COUNT(Name)
FROM Lead
GROUP BY LeadSource
HAVING COUNT(Name) > 100 AND COUNT(Name) < 200
SOQL.of(Lead.SObjectType)
.with(Lead.LeadSource)
.count(Lead.Name)
.groupBy(Lead.LeadSource)
.have('COUNT(Name) > 100 AND COUNT(Name) < 200')
.toAggregated();
havingConditionLogic​
Set conditions order for SOQL HAVING clause. When not specify all conditions will be with AND.
Signature
Queryable havingConditionLogic(String order)
Example
SELECT LeadSource, COUNT(Name)
FROM Lead
GROUP BY LeadSource, City
HAVING COUNT(Name) > 100 OR City LIKE 'San%'
SOQL.of(Lead.SObjectType)
.with(Lead.LeadSource)
.count(Lead.Name)
.groupBy(Lead.LeadSource)
.groupBy(Lead.City)
.have(SOQL.HavingFilter.count(Lead.Name).greaterThan(100))
.have(SOQL.HavingFilter.with(Lead.City).startsWith('San'))
.havingConditionLogic('1 OR 2')
.toAggregated();
anyHavingConditionMatching​
When the havingConditionLogic is not specified, all conditions are joined using the AND operator by default.
To change the default condition logic, you can utilize the anyHavingConditionMatching method, which joins conditions using the OR operator.
Signature
Queryable anyHavingConditionMatching()
Example
SELECT LeadSource, COUNT(Name)
FROM Lead
GROUP BY LeadSource, City
HAVING COUNT(Name) > 100 OR City LIKE 'San%'
SOQL.of(Lead.SObjectType)
.with(Lead.LeadSource)
.count(Lead.Name)
.groupBy(Lead.LeadSource)
.groupBy(Lead.City)
.have(SOQL.HavingFilter.count(Lead.Name).greaterThan(100))
.have(SOQL.HavingFilter.with(Lead.City).startsWith('San'))
.anyHavingConditionMatching()
.toAggregated();
ORDER BY​
orderBy​
Use the optional
ORDER BYin aSELECTstatement of a SOQL query to control the order of the query results.
Signature
Queryable orderBy(SObjectField field)
Queryable orderBy(String field)
Queryable orderBy(String field, String direction)
Example
SELECT Id
FROM Account
ORDER BY Name DESC
SOQL.of(Account.SObjectType)
.orderBy(Account.Name)
.sortDesc()
.toList();
SOQL.of(Account.SObjectType)
.orderBy('Name')
.sortDesc()
.toList();
SOQL.of(Account.SObjectType)
.orderBy('Name', 'DESC')
.toList();
orderBy related​
Order SOQL query by parent field.
Signature
Queryable orderBy(String relationshipName, SObjectField field)
Example
SELECT Id
FROM Contact
ORDER BY Account.Name
SOQL.of(Contact.SObjectType)
.orderBy('Account', Account.Name)
.toList();
orderBy COUNT​
Signature
Queryable orderByCount(SObjectField field)
Example
SELECT Industry
FROM Account
GROUP BY Industry
ORDER BY COUNT(Industry) DESC NULLS LAST
SOQL.of(Account.SObjectType)
.with(Account.Industry)
.groupBy(Account.Industry)
.orderByCount(Account.Industry).sortDesc().nullsLast()
.toAggregated();
sortDesc​
Default order is ascending (ASC).
Signature
Queryable sortDesc()
Example
SELECT Id
FROM Account
ORDER BY Name DESC
SOQL.of(Account.SObjectType)
.orderBy(Account.Name)
.sortDesc()
.toList();
sort​
Use ONLY for dynamic order.
Signature
Queryable sort(String direction)
Example
SELECT Id
FROM Account
ORDER BY Industry ASC NULLS FIRST
SOQL.of(Account.SObjectType)
.orderBy('Industry')
.sort('DESC')
.toList();
nullsLast​
By default, null values are sorted first (NULLS FIRST).
Signature
Queryable nullsLast()
Example
SELECT Id
FROM Account
ORDER BY Name NULLS LAST
SOQL.of(Account.SObjectType)
.orderBy(Account.Industry)
.nullsLast()
.toList();
nulls order​
To build dynamic order - use nullsOrder method.
Signature
Queryable nullsOrder(String order)
Example
SELECT Id
FROM Account
ORDER BY Name NULLS LAST
String order = 'LAST';
SOQL.of(Account.SObjectType)
.orderBy(Account.Industry)
.nullsOrder(order)
.toList();
LIMIT​
setLimit​
LIMITis an optional clause that can be added to aSELECTstatement of a SOQL query to specify the maximum number of rows to return.
Signature
Queryable setLimit(Integer amount)
Example
SELECT Id
FROM Account
LIMIT 100
SOQL.of(Account.SObjectType)
.setLimit(100)
.toList();
OFFSET​
offset​
When expecting many records in a query’s results, you can display the results in multiple pages by using the
OFFSETclause on a SOQL query.
Signature
Queryable offset(Integer startingRow)
Example
SELECT Id
FROM Account
OFFSET 10
SOQL.of(Account.SObjectType)
.setOffset(10)
.toList();
FOR​
forReference​
Use to notify Salesforce when a record is referenced from a custom interface, such as in a mobile application or from a custom page.
Signature
Queryable forReference()
Example
SELECT Id
FROM Contact
FOR REFERENCE
SOQL.of(Contact.SObjectType)
.forReference()
.toList();
forView​
Use to update objects with information about when they were last viewed.
Signature
Queryable forView()
Example
SELECT Id
FROM Contact
FOR VIEW
SOQL.of(Contact.SObjectType)
.forView()
.toList();
forUpdate​
Use to lock sObject records while they’re being updated in order to prevent race conditions and other thread safety problems.
Signature
Queryable forUpdate()
Example
SELECT Id
FROM Contact
FOR UPDATE
SOQL.of(Contact.SObjectType)
.forUpdate()
.toList();
allRows​
SOQL statements can use the ALL ROWS keywords to query all records in an organization, including deleted records and archived activities.
Signature
Queryable allRows()
Example
SELECT COUNT()
FROM Contact
ALL ROWS
SOQL.of(Contact.SObjectType)
.count()
.allRows()
.toList();
FIELD-LEVEL SECURITY​
By default AccessLevel is set as USER_MODE.
More details you can find in here
userMode​
By default, all queries are executed WITH USER_MODE. However, developers can override this. For more details, check Field-Level Security and Sharing Rules.
The userMode method can be useful to override the systemMode() provided by the selector.
Execution mode in which the object permissions, field-level security, and sharing rules of the current user are enforced.
Signature
Queryable userMode()
Example
SOQL.of(Account.SObjectType)
.userMode()
.toList();
systemMode​
Execution mode in which the the object and field-level permissions of the current user are ignored, and the record sharing rules are controlled by the class sharing keywords.
Signature
Queryable systemMode()
Example
SOQL.of(Account.SObjectType)
.systemMode()
.toList();
stripInaccessible​
USER_MODE enforces not only object and field-level security but also sharing rules (with sharing). You may encounter situations where you need object and field-level security but want to ignore sharing rules (without sharing). To achieve this, use .systemMode(), .withoutSharing() and .stripInaccessible().
Read more about stripInaccessible in advanced.
Signature
Queryable stripInaccessible()
Queryable stripInaccessible(AccessType accessType)
SOQL.of(Account.SObjectType)
.systemMode()
.withoutSharing()
.stripInaccessible()
.toList();
SHARING MODE​
Using the with sharing, without sharing, and inherited sharing Keywords
More details you can find in here.
withSharing​
Execute query with sharing.
Note! System mode needs to be enabled by .systemMode().
Signature
Queryable withSharing()
Example
SOQL.of(Account.SObjectType)
.systemMode()
.withSharing()
.toList();
withoutSharing​
Execute query without sharing.
Note! System mode needs to be enabled by .systemMode().
Signature
Queryable withoutSharing()
Example
SOQL.of(Account.SObjectType)
.systemMode()
.withoutSharing()
.toList();
MOCKING​
mockId​
Query needs unique id that allows for mocking.
Signature
Queryable mockId(String queryIdentifier)
Example
SOQL.of(Account.SObjectType)
.mockId('MyQuery')
.toList();
// In Unit Test
SOQL.mock('MyQuery').thenReturn(new List<Account>{
new Account(Name = 'MyAccount 1'),
new Account(Name = 'MyAccount 2')
});
record mock​
Signature
SOQL.Mockable mock(String mockId).thenReturn(SObject record)
Example
SOQL.of(Account.sObjectType)
.mockId('MyQuery')
.toList();
// In Unit Test
SOQL.mock('MyQuery').thenReturn(new Account(Name = 'MyAccount 1'));
list mock​
Signature
SOQL.Mockable mock(String mockId).thenReturn(List<SObject> records)
Example
SOQL.of(Account.sObjectType)
.mockId('MyQuery')
.toList();
// In Unit Test
SOQL.mock('MyQuery').thenReturn(new List<Account>{
new Account(Name = 'MyAccount 1'),
new Account(Name = 'MyAccount 2')
});
count mock​
Signature
SOQL.Mockable mock(String mockId).thenReturn(Integer amount)
Example
SOQL.of(Account.sObjectType)
.mockId('MyQuery')
.count()
.toInteger();
// In Unit Test
SOQL.mock('MyQuery).thenReturn(5);
aggregateResult mock​
Signature
SOQL.Mockable mock(String mockId).thenReturn(List<Map<String, Object>> mock);
SOQL.Mockable mock(String mockId).thenReturn(Map<String, Object> mock);
Example
List<Map<String, Object>> aggregateResults = new List<Map<String, Object>>{
new Map<String, Object>{ 'LeadSource' => 'Web', 'total' => 10},
new Map<String, Object>{ 'LeadSource' => 'Phone', 'total' => 5},
new Map<String, Object>{ 'LeadSource' => 'Email', 'total' => 3}
};
SOQL.mock('mockingQuery').thenReturn(aggregateResults);
List<SOQL.AggregateResultProxy> result = SOQL.of(Lead.SObjectType)
.with(Lead.LeadSource)
.COUNT(Lead.Id, 'total')
.groupBy(Lead.LeadSource)
.mockId('mockingQuery')
.toAggregatedProxy();
SObjectType mock​
Create a mock using SObjectType instead of a string identifier. This method automatically generates a hash-based mock ID from the SObjectType.
Signature
SOQL.Mockable mock(SObjectType ofObject)
Example
SOQL.of(Account.SObjectType)
.with(Account.Id, Account.Name)
.toList();
// In Unit Test - Mock records using SObjectType
SOQL.mock(Account.SObjectType).thenReturn(new List<Account>{
new Account(Name = 'Test Account 1'),
new Account(Name = 'Test Account 2')
});
// Mock single record using SObjectType
SOQL.mock(Contact.SObjectType).thenReturn(
new Contact(FirstName = 'John', LastName = 'Doe')
);
// Mock count using SObjectType
SOQL.mock(Lead.SObjectType).thenReturn(10);
Note! When using mock(SObjectType), the library automatically generates a mock identifier based on the SObjectType's hash code. This is convenient when you don't need to specify custom mock IDs and want to mock all queries for a specific SObject type.
exception mock​
Mock a query exception with default message.
Signature
SOQL.Mockable mock(String mockId).throwException()
Example
// In Unit Test
SOQL.mock('MyQuery').throwException();
Test.startTest();
Exception error;
try {
Account result = SOQL.of(Account.SObjectType)
.mockId('MyQuery')
.toObject();
} catch (Exception e) {
error = e;
}
Test.stopTest();
Assert.isNotNull(error, 'The query exception should be thrown.');
exception mock with message​
Mock a query exception with custom error message.
Signature
SOQL.Mockable mock(String mockId).throwException(String message)
Example
// In Unit Test
String errorMessage = 'No such column \'InvalidField__c\' on entity \'Account\'.';
SOQL.mock('MyQuery').throwException(errorMessage);
Test.startTest();
Exception error;
try {
Account result = SOQL.of(Account.SObjectType)
.mockId('MyQuery')
.toObject();
} catch (Exception e) {
error = e;
}
Test.stopTest();
Assert.isNotNull(error, 'The query exception should be thrown.');
Assert.isTrue(error.getMessage().contains('InvalidField__c'));
DEBUGGING​
preview​
Signature
Queryable preview()
Example
SOQL.of(Account.SObjectType)
.preview()
.toList();
Query preview will be available in debug logs:
============ Query Preview ============
SELECT Name, AccountNumber, BillingCity, BillingCountry, BillingCountryCode
FROM Account
WHERE ((Id = :v1 OR Name LIKE :v2))
=======================================
============ Query Binding ============
{
"v2" : "%Test%",
"v1" : "0013V00000WNCw4QAH"
}
=======================================
PREDEFINIED​
For all predefined methods SOQL instance is returned so you can still adjust query before execution.
Add additional fields with .with.
byId​
Signature
Queryable byId(Id recordId)
Queryable byId(SObject record)
Example
SELECT Id
FROM Account
WHERE Id = '1234'
SOQL.of(Account.SObjectType)
.byId('1234')
.toObject();
Account account = [SELECT Id FROM Account LIMIT 1];
SOQL.of(Account.SObjectType)
.byId(account)
.toObject();
byIds​
Signature
Queryable byIds(Iterable<Id> recordIds)
Queryable byIds(List<SObject> records)
Example
SELECT Id
FROM Account
WHERE Id IN ('1234')
SOQL.of(Account.SObjectType)
.byIds(new Set<Id>{ '1234' })
.toList();
SOQL.of(Account.SObjectType)
.byIds(new List<Id>{ '1234' })
.toList();
List<Account> accounts = [SELECT Id FROM Account];
SOQL.of(Account.SObjectType)
.byIds(accounts)
.toList();
byRecordType​
Query record by RecordType.DeveloperName. To do that, you can use the byRecordType method.
Signature
Queryable byRecordType(String recordTypeDeveloperName)
Example
SELECT Id
FROM Account
WHERE RecordType.DeveloperName = 'Partner'
SOQL.of(Account.SObjectType)
.byRecordType('Partner')
.toList();
RESULT​
toId​
Id toId()
Example
Id adminProfileId = SOQL.of(Profile.SObjectType)
.whereAre(SOQL.Filter.name().equal('System Administrator'))
.toId();
new User (
// ...
ProfileId = adminProfileId
);
toIds​
Extract all record IDs from query result.
Signature
Set<Id> toIds()
Example
Set<Id> accountIds = SOQL.of(Account.SObjectType)
.whereAre(SOQL.Filter.with(Account.Industry).equal('Technology'))
.toIds();
toIdsOf​
Extract field values as Set of IDs from query result. Field will be automatically added to the query fields.
Signature
Set<Id> toIdsOf(SObjectField field)
Example
Set<Id> ownerIds = SOQL.of(Account.SObjectType)
.whereAre(SOQL.Filter.with(Account.Industry).equal('Technology'))
.toIdsOf(Account.OwnerId);
toIdsOf Related Field​
Signature
Set<Id> toIdsOf(String relationshipName, SObjectField field)
Example
Set<Id> parentAccountIds = SOQL.of(Account.SObjectType)
.whereAre(SOQL.Filter.with(Account.Industry).equal('Technology'))
.toIdsOf('Parent', Account.Id);
doExist​
Signature
Boolean doExist()
Example
Boolean isRecordExist = SOQL.of(Account.SObjectType).byId('1234').doExist();
toValueOf​
Extract field value from query result. Field will be automatically added to the query fields.
Signature
Object toValueOf(SObjectField fieldToExtract)
Example
String accountName = (String) SOQL.of(Account.SObjectType).byId('1234').toValueOf(Account.Name)
toValuesOf​
Extract field values from query result. Field will be automatically added to the query fields.
SOQL Lib is using Building a KeySet from any field approach to get only one field.
Note! It does not work with Custom Metadata.
Signature
Set<String> toValuesOf(SObjectField fieldToExtract)
Example
Set<String> accountNames = SOQL.of(Account.SObjectType).byId('1234').toValuesOf(Account.Name)
toValuesOf Releated Field​
Signature
Set<String> toValuesOf(String relationshipName, SObjectField targetKeyField)
Example
Set<String> parentAccountNames = SOQL.of(Account.SObjectType)
.byId('1234')
.toValuesOf('Parent', Account.Name)
toInteger​
Signature
Integer toInteger()
Example
SELECT COUNT() FROM Account
SOQL.of(Account.SObjectType).count().toInteger();
toObject​
When the list of records contains more than one entry, the error List has more than 1 row for assignment to SObject will occur.
When there are no records to assign, the error List has no rows for assignment to SObject will NOT occur. This is automatically handled by the framework, and a null value will be returned instead.
Signature
sObject toObject()
Example
SOQL.of(Account.SObjectType).toObject();
toList​
Signature
List<sObject> toList()
Example
SOQL.of(Account.SObjectType).toList();
toAggregated​
Signature
List<AggregateResult> toAggregated()
Example
SELECT LeadSource
FROM Lead
GROUP BY LeadSource
SOQL.of(Lead.SObjectType)
.with(Lead.LeadSource)
.groupBy(Lead.LeadSource)
.toAggregated()
toMap​
Signature
Map<Id, SObject> toMap()
Example
Map<Id, Account> idToAccount = (Map<Id, Account>) SOQL.of(Account.SObjectType).toMap();
toMap with custom key​
Note! To improve query performance, a condition checking if the keyField is not null (WHERE keyField != null) is automatically added to the query.
Signature
Map<String, SObject> toMap(SObjectField keyField)
Example
Map<String, Account> nameToAccount = (Map<String, Account>) SOQL.of(Account.SObjectType).toMap(Account.Name);
toMap with custom relationship key​
Note! To improve query performance, a condition checking if the targetKeyField is not null (WHERE relationshipName.targetKeyField != null) is automatically added to the query.
Signature
Map<String, SObject> toMap(String relationshipName, SObjectField targetKeyField)
Example
Map<String, Account> parentCreatedByEmailToAccount = (Map<String, Account>) SOQL.of(Account.SObjectType).toMap('Parent.CreatedBy', User.Email);
toMap with custom key and value​
Note! To improve query performance, a condition checking if the keyField is not null (WHERE keyField != null) is automatically added to the query.
Signature
Map<String, String> toMap(SObjectField keyField, , SObjectField valueField)
Example
Map<String, String> nameToAccount = SOQL.of(Account.SObjectType).toMap(Account.Name, Account.Industry);
toAggregatedMap​
Note! To improve query performance, a condition checking if the keyField is not null (WHERE keyField != null) is automatically added to the query.
Signature
Map<String, List<SObject>> toAggregatedMap(SObjectField keyField)
Example
Map<String, List<Account>> industryToAccounts = (Map<String, List<Account>>) SOQL.of(Account.SObjectType).toAggregatedMap(Account.Industry);
toAggregatedMap with custom value​
Note! To improve query performance, a condition checking if the keyField is not null (WHERE keyField != null) is automatically added to the query.
Signature
Map<String, List<String>> toAggregatedMap(SObjectField keyField, SObjectField valueField)
Example
Map<String, List<String>> industryToAccounts = SOQL.of(Account.SObjectType).toAggregatedMap(Account.Industry, Account.Name);
toAggregatedMap with custom relationship key​
Note! To improve query performance, a condition checking if the targetKeyField is not null (WHERE relationshipName.targetKeyField != null) is automatically added to the query.
Signature
Map<String, List<SObject>> toAggregatedMap(String relationshipName, SObjectField targetKeyField)
Example
Map<String, List<Account>> parentCreatedByEmailToAccounts = (Map<String, List<Account>>) SOQL.of(Account.SObjectType).toAggregatedMap('Parent.CreatedBy', User.Email);
toIdMapBy​
Creates a map where the key is the Id extracted from the specified field and the value is the SObject record.
Note! To improve query performance, a condition checking if the field is not null (WHERE field != null) is automatically added to the query.
Signature
Map<Id, SObject> toIdMapBy(SObjectField field)
Example
Map<Id, Account> ownerIdToAccount = (Map<Id, Account>) SOQL.of(Account.SObjectType).toIdMapBy(Account.OwnerId);
toIdMapBy with relationship​
Creates a map where the key is the Id extracted from the specified relationship field and the value is the SObject record.
Note! To improve query performance, a condition checking if the targetKeyField is not null (WHERE relationshipName.targetKeyField != null) is automatically added to the query.
Signature
Map<Id, SObject> toIdMapBy(String relationshipName, SObjectField targetKeyField)
Example
Map<Id, Account> parentIdToAccount = (Map<Id, Account>) SOQL.of(Account.SObjectType).toIdMapBy('Parent', Account.Id);
toAggregatedIdMapBy​
Creates a map where the key is the Id extracted from the specified field and the value is a list of SObject records grouped by that Id.
Note! To improve query performance, a condition checking if the keyField is not null (WHERE keyField != null) is automatically added to the query.
Signature
Map<Id, List<SObject>> toAggregatedIdMapBy(SObjectField keyField)
Example
Map<Id, List<Account>> ownerIdToAccounts = (Map<Id, List<Account>>) SOQL.of(Account.SObjectType).toAggregatedIdMapBy(Account.OwnerId);
toAggregatedIdMapBy with relationship​
Creates a map where the key is the Id extracted from the specified relationship field and the value is a list of SObject records grouped by that Id.
Note! To improve query performance, a condition checking if the targetKeyField is not null (WHERE relationshipName.targetKeyField != null) is automatically added to the query.
Signature
Map<Id, List<SObject>> toAggregatedIdMapBy(String relationshipName, SObjectField targetKeyField)
Example
Map<Id, List<Account>> parentIdToAccounts = (Map<Id, List<Account>>) SOQL.of(Account.SObjectType).toAggregatedIdMapBy('Parent', Account.Id);
toQueryLocator​
Signature
Database.QueryLocator toQueryLocator()
Example
SOQL.of(Account.SObjectType).toQueryLocator();
toCursor​
Returns a Database.Cursor for the query, which can be used for more efficient processing of large result sets with streaming capabilities.
Signature
Database.Cursor toCursor()
Example
Database.Cursor cursor = SOQL.of(Account.SObjectType)
.with(Account.Id, Account.Name)
.whereAre(SOQL.Filter.with(Account.Industry).equal('Technology'))
.toCursor();
toPaginationCursor​
Returns a Database.PaginationCursor for the query, which enables efficient pagination through large result sets with built-in offset management.
Signature
Database.PaginationCursor toPaginationCursor()
Example
Database.PaginationCursor paginationCursor = SOQL.of(Account.SObjectType)
.with(Account.Id, Account.Name, Account.Industry)
.whereAre(SOQL.Filter.with(Account.Industry).equal('Technology'))
.orderBy(Account.Name)
.setLimit(100)
.toPaginationCursor();