[SalesForce] How to create very generic dynamic SOSL query

I have this below method which i want to make it more generic which can be used for any object and pass any filter to SOSL query according to object passed(build dynamic) . From lightning component i will be passing object name. How to do it.
How can i use a dynamic variable after RETURNING word to pass any Object

 @AuraEnabled(Cacheable=true)
    public static List<LookupSearchResult> searchCountries(String searchTerm, List<String> selectedIds, String objectName) {
        system.debug('searchTerm' + searchTerm);
        // Prepare query paramters
        searchTerm += '*';

        // Execute search query
        List<List<SObject>> searchResults = [FIND :searchTerm IN ALL FIELDS RETURNING
                                             Test__c (Id, Name WHERE Name NOT IN :selectedIds)
                                             LIMIT :MAX_RESULTS];
        system.debug('searchResults' + searchResults);
        // Prepare results
        List<LookupSearchResult> results = new List<LookupSearchResult>();

        String geoIcon = 'custom:custom9';
        Test__c [] tst = ((List<Test__c >) searchResults[0]);
        for (Test__c t: tst) {
            results.add(new LookupSearchResult(t.Id, 'Test__c', geoIcon, t.Name, 'Test • '));
        }

        return results;
    }

LookupSearchResult.cls

public class LookupSearchResult {
private Id id;
    private String sObjectType;
    private String icon;
    private String title;
    private String subtitle;

        public LookupSearchResult(Id id, String sObjectType, String icon, String title, String subtitle) {
            this.id = id;
            this.sObjectType = sObjectType;
            this.icon = icon;
            this.title = title;
            this.subtitle = subtitle;
        }
    }

Best Answer

You can use this method. This can be used for both SOQL or SOSL.

Parameter params is a generic way of passing the data from client-side to apex method - can add/remove any part of data for scalability.

  1. fields - comma separated fields (can have relation-ship fields too)

  2. objectName - api name of object from where you need to query

  3. filters - String which would represent filter conditions. Eg: Id='0TB******' AND Status IN ('New','Closed')
  4. queryType - SOQL or SOSL
  5. orderBy - field name by which the records should be ordered by
  6. sortAsc - order by acending if true else by descending order
  7. limitStr - limit Integer converted to string for limiting the number of records in query
  8. soslSearchTerm - search text for SOSL. This is mandatory and minimum 2 characters if query type is SOSL.

Find below the method:

public with sharing class myCLass {
    @AuraEnabled
    public static List<sObject> getRecordsList(Map<String, Object> params) {
        try{
            String fields = params.containsKey('fields') ? (String)params.get('fields') : null;
            String objectName = params.containsKey('objectName') ? (String)params.get('objectName') : null;
            String filters = params.containsKey('filters') ? (String)params.get('filters') : null;
            String queryType = params.containsKey('queryType') ? (String)params.get('queryType') : null;
            String orderBy = params.containsKey('orderBy') ? (String)params.get('orderBy') : null;
            Boolean sortAsc = params.containsKey('sortAsc') ? (Boolean)params.get('sortAsc') : false;
            String limitStr = params.containsKey('limitStr') ? (String)params.get('limitStr') : null;
            String soslSearchTerm = params.containsKey('soslSearchTerm') ? (String)params.get('soslSearchTerm') : null;

            List<sObject> sObjectsList = new List<sObject>();
            String query;

            if(queryType == 'SOQL'){
                query = 'SELECT Id, ' + fields + ' FROM ' + objectName;
            }
            else if(queryType == 'SOSL') {
                query = 'Id, ' + fields;
            }

            if(String.isNotBlank(filters)){
                query += ' WHERE ' + filters;
            }

            if(String.isNotBlank(orderBy) && queryType == 'SOQL'){
                query += ' ORDER BY ' + orderBy + (sortAsc?' ASC ':' DESC ');
            }

            if(String.isNotBlank(limitStr)) {
                query += ' LIMIT ' + limitStr;
            }

            if(queryType == 'SOQL'){
                system.debug('query => '+query);
                sObjectsList = Database.query(query);
            }
            else if(queryType == 'SOSL') {
                query = 'FIND \'' + String.escapeSingleQuotes(soslSearchTerm) + '\' IN ALL FIELDS RETURNING ' + objectName + '(' + query + ')';
                system.debug('query => '+query);
                sObjectsList = Search.query(query)[0];
            }
            system.debug('sObjectsList => '+sObjectsList);

            return sObjectsList;     
        }
        catch(Exception ex) {
            system.debug('Error => '+ex.getMessage());
            throw new AuraHandledException(ex.getMessage());
        }   
    }
}

IMPORTANT:

  1. No parameter of this method should be directly exposed to user entry as it is injection vulnerability. However predefined options can be exposed like select-options, checkboxes etc.
  2. If this method is being used to retrieve sensitive data, FLS check should be manually applied on fields.
  3. This method can be taken only as a starting step for creating more complex dynamic queries in SOQL/SOSL.
Related Topic