0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Apex_SOSLでグローバル検索(匿名実行)

Posted at

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省略できなかったから作成してみた!
何か参考になれば嬉しいな!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?