Is this possible? I would like to do the following directly:
Set<String> titles = new Set<String>([Select Title From SObject]);
Salesforce Stack Exchange is a question and answer site for Salesforce administrators, implementation experts, developers and anybody in-between. It only takes a minute to sign up.
Sign up to join this communityIs this possible? I would like to do the following directly:
Set<String> titles = new Set<String>([Select Title From SObject]);
No it is not possible except for Set<Id>
. With other types, you need a for
loop:
Set<String> names = new Set<String>();
for (MyObject__c record : [SELECT Name FROM MyObject__c])
names.add(record.Name);
The special case is that with a record's own Id, you can use this Map constructor:
Set<Id> ids = new Map<Id, SObject>([/*query*/]).keySet();
You can abuse this shortcut and field alias functionality in aggregate queries to get a collection of parent Ids also.
Set<Id> parentIds = new Map<Id, SObject>([
SELECT Parent__c Id FROM MyObject__c GROUP BY Parent__c
// ^^ you can now call .get('Id') on a result record
]).keySet();
GROUP BY
clause.
Expanding on Adrian's answer of using the aggregate field alias to unpack a parent Id into a Set.
Adrian's version:
Set<Id> parentIds = new Map<Id, SObject>([
SELECT Parent__c Id FROM MyObject__c GROUP BY Parent__c
// ^^ you can now call .get('Id') on a result record
]).keySet();
I came across this expanded version by @mattandneil - Building a Set from any field
Matt's version:
Set<String> names = new Map<String,SObject>([
SELECT Name Id
FROM User
GROUP BY Name
]).keySet();
The key different being that the aliased field doesn't actually have to be an Id
. It could be a String
, or Date
. You just need to be able to GROUP BY it and adjust the map key accordingly.
As noted by the current Apex PM Chris Peterson, if you use this in production ensure that it is covered by Apex test cases that the hammer tests will see.
String
and Date
fields but no other types? Interesting.
You can do it fairly easily for the Set of Id use case by passing the SOQL to the constructor of an Id to Sobject Map and then grabbing the keyset from this;-
Set<Id> Ids = new Map<Id, Sobject>([SELECT Id FROM SObject]).keySet();
Other than that though there isn't a direct way to do it for non-Id fields. Your best bet would probably to create a reusable worker method to handle this.
Depending on what you need this for aggregate SOQL functions may help as they will produce a list of all unique values for the aggregated field.
Set<String> titles = new Set<String>();
for(AggregateResult ar : [SELECT Title FROM SObject GROUP BY Title]){
titles.add((String)ar.get('Title'));
}