Salesforceの開発者コンソール(Open Execute Anonymous Window)を使用して、匿名実行でグローバル検索するコード作成したよ!
全オブジェクト、Apexクラスなどのコードも対象にするよ!
以下、サンプルコードだよ!開発者コンソールの匿名実行で実行してみてね!
// すべてのSObject(標準オブジェクト、カスタムオブジェクト含む)の定義を取得し、
// キーにAPI名、値にSchema.SObjectTypeを持つMapとして返される
Map<String, Schema.SObjectType> globalDescribe = Schema.getGlobalDescribe();
// 取得したMapからオブジェクトAPI名のリストを作成
List<String> objectNames = new List<String>(globalDescribe.keySet());
// オブジェクトAPI名をアルファベット順にソート
objectNames.sort();
// 検索したいワード
String searchKeyword = 'Test';
// シングルクォートをエスケープして文字列を生成
String soslKeyword = String.escapeSingleQuotes(searchKeyword);
// ワイルドカード(*)を付ける
soslKeyword = '*' + soslKeyword + '*';
System.debug('検索値: ' + soslKeyword);
// SOSL文の「RETURNING句」を組み立てるための変数を初期化
String returningClause = 'RETURNING ';
// ソートしたオブジェクト名のリストを走査
for (String objectName : objectNames) {
// このオブジェクトの詳細情報を取得
Schema.DescribeSObjectResult objDescribe = globalDescribe.get(objectName).getDescribe();
// 検索可能かどうか判定(isSearchableがtrueのものだけを対象にする)
if (objDescribe.isSearchable()) {
// 「オブジェクト名(Id,」の部分をRETURNING句に追加
returningClause += objectName + '(Id, ';
// 全フィールド定義を取得(キーがフィールドAPI名、値がフィールド定義)
Map<String, Schema.SObjectField> fieldMap = objDescribe.fields.getMap();
// Nameフィールドが見つかったかどうかのフラグ
Boolean foundNameField = false;
// 全フィールド名を走査して「Name」と一致するものがあるか確認
for (String fieldName : fieldMap.keySet()) {
// フィールド名がName(大小文字無視)なら
if (fieldName.toLowerCase() == 'name') {
// RETURNING句にNameを追加
returningClause += fieldName;
// フラグを立ててループを抜ける
foundNameField = true;
break;
}
}
// Nameフィールドが無かった場合は文字列型またはテキストエリア型のフィールドを検索
if (!foundNameField) {
for (Schema.SObjectField field : fieldMap.values()) {
// 各フィールドの詳細を取得
Schema.DescribeFieldResult fieldDescribe = field.getDescribe();
// String型またはTextArea型なら
if (fieldDescribe.getType() == Schema.DisplayType.String
|| fieldDescribe.getType() == Schema.DisplayType.TextArea) {
// RETURNING句にフィールド名を追加
returningClause += fieldDescribe.getName();
// 一つ見つかったら抜ける
break;
}
}
}
// 1つのオブジェクト分のRETURNING句を区切る(カンマとスペースを加える)
returningClause += '), ';
}
}
// 末尾に残っている「, 」を削除してRETURNING句を整える
returningClause = returningClause.removeEnd(', ');
// 検索キーワードを動的に組み込んだSOSL文の作成
String soslQuery = 'FIND {' + soslKeyword + '} IN ALL FIELDS ' + returningClause;
// 組み立てたSOSL文を実行し、検索結果を「List<List<SObject>>」形式で受け取る
List<List<SObject>> searchResults = Search.query(soslQuery);
// 各オブジェクトごとの検索結果のリストを走査
for (List<sObject> objectResults : searchResults) {
// レコード1件ごとに処理
for (sObject obj : objectResults) {
// レコードが属するオブジェクトのAPI名を取得
String objectApiName = obj.getSObjectType().getDescribe().getName();
// レコードが属するオブジェクトのラベル名を取得
String objectLabel = obj.getSObjectType().getDescribe().getLabel();
// レコードのIdを取得
String id = obj.Id;
// Nameや文字列型フィールドの値を保持する変数を用意
String nameOrLabel = '';
// 改めてこのレコードのオブジェクトの詳細情報を取得
Schema.DescribeSObjectResult objDescribe = obj.getSObjectType().getDescribe();
// フィールド定義のマップを取得(API名 -> 定義オブジェクト)
Map<String, Schema.SObjectField> fieldMap = objDescribe.fields.getMap();
// Nameフィールドを見つけたかどうかのフラグ
Boolean foundNameField = false;
// 全フィールド名を走査してNameフィールドがあるか確認
for (String fieldName : fieldMap.keySet()) {
// フィールド名がNameなら
if (fieldName.toLowerCase() == 'name') {
// 実際の値をobjから取得してnameOrLabelに格納
nameOrLabel = String.valueOf(obj.get(fieldName));
// フラグをtrueにしてループを抜ける
foundNameField = true;
break;
}
}
// Nameフィールドが無い場合は文字列型かテキストエリア型を探索
if (!foundNameField) {
for (Schema.SObjectField field : fieldMap.values()) {
// フィールドの詳細を取得
Schema.DescribeFieldResult fieldDescribe = field.getDescribe();
// 文字列型かテキストエリア型か判定
if (fieldDescribe.getType() == Schema.DisplayType.String
|| fieldDescribe.getType() == Schema.DisplayType.TextArea) {
// objから値を取り出してnameOrLabelに格納
nameOrLabel = String.valueOf(obj.get(fieldDescribe.getName()));
break;
}
}
}
// デバッグログにオブジェクトAPI名、ラベル名、Id、名前フィールド(または文字列フィールド)を出力
System.debug(
'オブジェクト API名 = ' + objectApiName
+ ' (オブジェクト ラベル = ' + objectLabel + ' ), '
+ 'Id = ' + id
+ ', Name/Label = ' + nameOrLabel
);
}
}
匿名実行だと、RETURNING省略できなかったから作成してみた!
何か参考になれば嬉しいな!