| |

Salesforce SOSL Cheatsheet, Interview Questions & Scenarios

If you are revising for a Salesforce Interview and want a quick look at SOSL, then you are in the right place.

In this Blog, you will get the Salesforce SOSL cheatsheet covering everything from basic syntax to wildcards, search groups, governor limits, and real-world scenarios — all in one place.

NOTE: Don’t forget to check the Scenario Based Questions at the end. Similar questions are commonly asked in top MNCs such as TCS / Infosys / Wipro / Accenture / IBM / Cognizant / Deloitte.

SOSL CHEATSHEET

Where to use SOSL?

Real world Scenario

Imagine that during a client project, you had a requirement in which support agents only knew a customer’s surname. Running separate SOQL queries against Account, Contact, and Lead became inefficient, which made SOSL the obvious solution because we can search all three objects at once using SOSL.

What is SOSL

Think of SOSL as Salesforce’s cross-object search engine. Instead of querying one object at a time, you can submit a search term and let Salesforce scan multiple objects and searchable fields in a single operation.

NOTE: In the Query Editor and API, the search term is enclosed in curly brackets – FIND {SHARMA}. In Apex (inline SOSL), the search term is enclosed in single quotes – FIND ‘SHARMA’. This difference is frequently tested in interviews.

SOSL vs SOQL – When to Use Which

  • You know exactly which object to query
  • You need structured filtering (WHERE, GROUP BY)
  • You need aggregate functions (COUNT, SUM)
  • You are doing DML operations after querying
  • You need relationship queries (parent-child)
  • You don’t know which object holds the data
  • You need to search across multiple objects at once
  • You are building a global search feature
  • You need full-text search across email, phone, name
  • Search term could be in any field type

Basic SOSL Syntax

A complete SOSL query in Apex looks like this:


// Complete SOSL query searching for 'Wingo' across Account and Contact
List<List<SObject>> results = [
    FIND 'Sharma'
    IN ALL FIELDS
    RETURNING
        Account(Name),
        Contact(FirstName, LastName, Email)
];

// Access results by index — same order as RETURNING clause
List<Account> accounts = (List<Account>) results[0];
List<Contact> contacts = (List<Contact>) results[1];

Text searches in SOSL are always case-insensitive. Searching for “Sharma”, “sharma”, or “SHARMA” all return the same results. This is a common interview trick question.


Search Groups (IN Clause)

Real world Scenario

Imagine that a bank’s compliance team wants to search for the term “fraud” but only within email fields of Contacts and Leads – not in names or phone numbers. Using IN EMAIL FIELDS scopes the search precisely to only email fields across all specified objects.

The IN clause defines the scope of fields to search. If not specified, the default is ALL FIELDS.


// Searches Name, email, phone, text, and other indexed fields
FIND 'Sharma' IN ALL FIELDS RETURNING Account(Name), Contact(LastName)

// Searches ONLY Name fields across specified objects
FIND 'Sharma' IN NAME FIELDS RETURNING Account(Name), Lead(LastName)

// Searches ONLY email fields — useful for finding contacts by email domain
FIND '@sharmacorp.com' IN EMAIL FIELDS RETURNING Contact(Name, Email), Lead(Email)

// Searches ONLY phone fields — useful for finding records by phone number
FIND '9876543210' IN PHONE FIELDS RETURNING Contact(Name, Phone), Account(Phone)

// Searches sidebar fields — legacy Salesforce sidebar search scope
FIND 'Sharma' IN SIDEBAR FIELDS RETURNING Account(Name)

Search Group

Fields Searched

Best Used For

ALL FIELDS

Name, email, phone, text, and other indexed fields

General global search -default

NAME FIELDS

Name fields only

Searching by person or company name

EMAIL FIELDS

Email fields only

Searching by email address or domain

PHONE FIELDS

Phone fields only

Searching by phone number

SIDEBAR FIELDS

Legacy sidebar fields

Legacy use – rarely used today

IN ALL FIELDS does NOT mean it searches every single field on an object. It searches fields that are indexed and searchable by Salesforce, such as name, email, phone, and certain text fields. Formula fields, long text areas beyond a certain length, and encrypted fields are NOT searched.


Single Words and Phrases

Real world Scenario

A support manager at an e-commerce company is looking for a customer named “John Smith”. Searching for ‘John Smith’  (as a phrase in double quotes) returns only records with that exact phrase, not records that just contain “John” or just “Smith” separately. This is critical when searching for full names or exact product codes.

A SOSL search query contains two types of text:


// Single word — finds all records containing this word anywhere
FIND 'Sharma' IN ALL FIELDS RETURNING Account(Name)

// Phrase — double quotes inside single quotes — exact phrase match
FIND '"rahul sharma"' IN ALL FIELDS RETURNING Contact(FirstName, LastName)

// OR operator — returns records matching either word
FIND 'Sharma OR Kumar' IN ALL FIELDS RETURNING Account(Name), Contact(LastName)

// AND operator — returns records matching both words
FIND 'Sharma AND Kumar' IN ALL FIELDS RETURNING Account(Name)

// Numeric search — finds phone numbers ending in 1212
// The dash delimiters make 1212 a searchable word
FIND '1234' IN PHONE FIELDS RETURNING Contact(Name, Phone), Account(Name, Phone)

Wildcards in SOSL

Real world Scenario

A sales rep at a software company remembers the customer’s name starts with “sha” but cannot remember the rest. Using the wildcard sha* returns all records where any searchable field starts with “sha” — including “Sharma”, “shawn Technologies”, and “Shanaya Solutions” — without needing to know the exact spelling.


// * wildcard — matches ZERO or more characters at middle or end
FIND 'sha*' IN ALL FIELDS RETURNING Account(Name), Contact(LastName)
// Matches: Sharma, Shawn, Shanaya, shayan

// * at end — prefix search (most common)
FIND 'Sales*' IN ALL FIELDS RETURNING Account(Name)
// Matches: Sales, Salesforce, Salesman, Salesperson

// * at middle — matches any characters in the middle
FIND 'S*force' IN ALL FIELDS RETURNING Account(Name)
// Matches: Salesforce, Skyforce

// ? wildcard — matches EXACTLY ONE character at middle or end
FIND 'Sale?' IN ALL FIELDS RETURNING Account(Name), Contact(LastName)
// Matches: Sales, Saled, Salef — does NOT match Sale or Salesforce

// Combine wildcards for flexible search
FIND 'cl?ud*' IN ALL FIELDS RETURNING Account(Name)
// Matches: cloud, clouds, cloudy, claud, claudio

*

Zero or more characters

sha*

Sharma, Shawn, Shanaya

asha (start of word)

?

Exactly ONE character

sale?

Sales, Saled

Sale, Salesforce

EXAM TRAP: Wildcards only work at the middle or end of a search term – NOT at the very beginning. You cannot write ‘*force’ at the start of a query. A leading wildcard is not supported and will either return no results or throw an error.

Search Group


Filters, ORDER BY and LIMIT inside RETURNING

Real world Scenario

A marketing team’s global search tool searches for the keyword “cloud” across Accounts and Contacts. However, they only want Accounts in the Technology industry, ordered alphabetically, limited to 10 results. They also only want Contacts who are linked to an Account (not orphaned Contacts). All of this filtering happens inside the RETURNING clause — not in a WHERE clause at the top level.


List<List<SObject>> results = [
    FIND 'cloud*'                        // wildcard — anything starting with cloud
    IN ALL FIELDS
    RETURNING
        Account(Id, Name
                WHERE Industry = 'Technology'   // filter inside RETURNING
                ORDER BY Name ASC             // order inside RETURNING
                LIMIT 10),                    // limit per object
        Contact(Id, FirstName, LastName, Email
                WHERE AccountId != NULL       // only Contacts linked to an Account
                ORDER BY LastName ASC
                LIMIT 20),
        Lead(Id, FirstName, LastName
             WHERE IsConverted = false        // only unConverted Leads
             LIMIT 5)
    LIMIT 200                                 // total records across ALL objects combined
];

SOSL has two LIMIT clauses. The LIMIT inside each object in the RETURNING clause limits results per object. The LIMIT at the end of the whole query limits the total records across all objects combined. Both can be used together.

You cannot use GROUP BY, HAVING, or aggregate functions like COUNT() or SUM() inside a SOSL query. Those are SOQL-only features. SOSL is a text search tool — not a data aggregation tool.


SOSL in Apex – Inline SOSL

Real world Scenario

A Salesforce developer at an insurance company is building a “Universal Search” feature. When a user types a policy number or customer name into a search box and clicks Search, the LWC calls an Apex method that runs an inline SOSL query across Account, Contact, and Case objects — returning results from all three in one call.

This is the implementation of a search method using SOSL in Apex.


public with sharing class GlobalSearchController {

    @AuraEnabled(cacheable=true)
    public static Map<String, List<SObject>> globalSearch(String keyword) {

        // Validate input
        if (String.isBlank(keyword)) {
            return new Map<String, List<SObject>>();
        }

        // Sanitize for wildcard search
        String searchTerm = String.escapeSingleQuotes(keyword) + '*';

        // Inline SOSL — embedded directly in Apex
        List<List<SObject>> results = [
            FIND :searchTerm
            IN ALL FIELDS
            RETURNING
                Account(Id, Name, Industry, Phone),
                Contact(Id, FirstName, LastName, Email),
                Case(Id, CaseNumber, Subject, Status)
            LIMIT 100
        ];

        // Map results to object names for easy access in LWC
        Map<String, List<SObject>> resultMap =
            new Map<String, List<SObject>>();

        resultMap.put('Accounts',  results[0]);
        resultMap.put('Contacts',  results[1]);
        resultMap.put('Cases',     results[2]);

        return resultMap;
    }
}

BEST PRACTICE: Always validate and sanitize the search term before using it in a SOSL query. Blank or null search terms will throw a System.SearchException.Use String.isBlank() to guard against this.

Accessing SOSL Results

After a SOSL query returns results for Account, Contact, and Opportunity, the developer needs to loop through each object’s results separately and display them in different sections of a dashboard.

Each object’s results are accessed by their index position in the result list.


List<List<SObject>> searchResults = [
    FIND 'TechCorp'
    IN ALL FIELDS
    RETURNING
        Account(Id, Name, Industry),
        Contact(Id, FirstName, LastName, Email),
        Opportunity(Id, Name, StageName, Amount)
];

// Each index maps to each object in RETURNING — same order
List<Account>     accounts = (List<Account>)     searchResults[0];
List<Contact>     contacts = (List<Contact>)     searchResults[1];
List<Opportunity> opps     = (List<Opportunity>) searchResults[2];

// Process Accounts
for (Account acc : accounts) {
    System.debug('Account: ' + acc.Name + ' | Industry: ' + acc.Industry);
}

// Process Contacts
for (Contact con : contacts) {
    System.debug('Contact: ' + con.FirstName + ' ' + con.LastName
        + ' | Email: ' + con.Email);
}

// Process Opportunities
for (Opportunity opp : opps) {
    System.debug('Opp: ' + opp.Name + ' | Stage: ' + opp.StageName
        + ' | Amount: ' + opp.Amount);
}

// Check result counts
System.debug('Accounts found: '  + accounts.size());
System.debug('Contacts found: '  + contacts.size());
System.debug('Opps found: '     + opps.size());

The return type of a SOSL query is List<List<sObject>> — a list of lists. Each inner list must be cast to the correct SObject type using explicit casting before you can access specific fields. Without the cast, you can only access the ID field.

Dynamic SOSL

Real world Scenario

Suppose you want to create a customized multi-object search bar, where you can input the search keyword from the UI, select which object to search from the checkbox, and after selecting the checkbox, there will be a multi-select picklist to select the fields you want to search.

A Dynamic SOSL allows you to build a flexible system where search keyword, Object and fields are computed at runtime.

You can use Search.query() method execute your SOSL query.


public with sharing class DynamicSearchService {

    public static List<List<SObject>> dynamicSearch(
        String keyword,
        String objectName,
        List<String> fields) {

        // Validate
        if (String.isBlank(keyword)) return new List<List<SObject>>();

        // Sanitize inputs
        String safeKeyword = String.escapeSingleQuotes(keyword);
        String safeObject  = String.escapeSingleQuotes(objectName);
        String fieldList   = String.join(fields, ', ');

        // Build dynamic SOSL string
        String sosl = 'FIND \''    + safeKeyword + '*\''
                    + ' IN ALL FIELDS'
                    + ' RETURNING '   + safeObject
                    + '('             + fieldList   + ')'
                    + ' LIMIT 50';

        // Execute dynamic SOSL using Search.query()
        return Search.query(sosl);
    }
}

NOTE: For dynamic SOSL, use Search.query(String sosl) instead of inline SOSL. This is the equivalent of Database.query() for SOQL. Always sanitize dynamic inputs using String.escapeSingleQuotes() to prevent SOSL injection attacks.

Enforcing Security in SOSL

A financial services firm has a global search feature accessible to all employees. However, not all employees can see the SSN__c field on Contact records. Without security enforcement, SOSL would return SSN__c values to users who should never see them. Using WITH USER_MODE or Security.stripInaccessible() ensures each user only sees what they are allowed to see.


// WITH USER_MODE — enforces FLS, CRUD, and sharing rules
// Throws System.QueryException if user lacks access
List<List<SObject>> results = [
    FIND 'TechCorp'
    IN ALL FIELDS
    RETURNING Account(Id, Name, AnnualRevenue)
    WITH USER_MODE
];

// WITH SYSTEM_MODE — bypasses all permissions (use carefully)
List<List<SObject>> sysResults = [
    FIND 'TechCorp'
    IN ALL FIELDS
    RETURNING Account(Id, Name)
    WITH SYSTEM_MODE
];

// Security.stripInaccessible() — silently removes restricted fields
// Does NOT throw exception — safer for UI use cases
List<List<SObject>> rawResults = [
    FIND 'TechCorp'
    IN ALL FIELDS
    RETURNING Contact(Id, Name, SSN__c, Email)
];

SObjectAccessDecision decision = Security.stripInaccessible(
    AccessType.READABLE,
    rawResults[0]   // pass one object's list at a time
);
List<Contact> safeContacts = (List<Contact>) decision.getRecords();
// SSN__c silently removed if user has no FLS access to it

Object-Level (CRUD)

Enforced

Bypassed

Bypassed (System mode)

Field-Level (FLS)

Enforced

Bypassed

Bypassed (System mode)

Sharing Rules

Enforced

Bypassed

Inherits class context

On restriction

Throws QueryException

Returns all data

Returns all data


GOVERNOR LIMITS — Must Memorise

Below are the governor limits specific to SOSL as per Salesforce official documentation:

20

2,000

200

3

Queries per transaction

20

100

Records returned per query

2,000

50,000

Objects searched in one query

Multiple

One

Aggregate functions supported

NO

YES

Relationship queries supported

NO

YES

Result type

List<List<sObject>>

List<sObject>

EXAM TRAP: SOSL has a limit of 20 queries per transaction (vs 100 for SOQL) and only returns 2,000 records max (vs 50,000 for SOQL). If your use case requires more than 2,000 records, you must use SOQL instead of SOSL.


SOSL SCENARIO BASED QUESTIONS

Write a SOSL query to search for the keyword “Salesforce” across Account, Contact, and Lead objects. Return Name from Account, FirstName and LastName from Contact, and Company from Lead.


// APEX CODE
List<List<SObject>> results = [
    FIND 'Salesforce'
    IN ALL FIELDS
    RETURNING
        Account(Id, Name),
        Contact(Id, FirstName, LastName),
        Lead(Id, FirstName, LastName, Company)
];

List<Account> accounts = (List<Account>) results[0];
List<Contact> contacts = (List<Contact>) results[1];
List<Lead>    leads    = (List<Lead>)    results[2];

Write a SOSL query to search for “TechCorp” in NAME FIELDS only. Return Accounts where Industry is ‘Technology’ and Contacts where AccountId is not null. Limit Account results to 5 and Contact results to 10.


// APEX CODE
List<List<SObject>> results = [
    FIND 'TechCorp'
    IN NAME FIELDS
    RETURNING
        Account(Id, Name, Industry
                WHERE Industry = 'Technology'
                LIMIT 5),
        Contact(Id, FirstName, LastName, Email
                WHERE AccountId != NULL
                LIMIT 10)
];

List<Account> accounts = (List<Account>) results[0];
List<Contact> contacts = (List<Contact>) results[1];

Write a SOSL query to sWrite a complete Apex method searchByKeyword(String keyword) that accepts a search term, appends a wildcard * to it, searches across Account and Contact in ALL FIELDS, and returns a Map with keys ‘Accounts’ and ‘Contacts’ containing the respective results. Handle blank input gracefully.
earch for “TechCorp” in NAME FIELDS only. Return Accounts where Industry is ‘Technology’ and Contacts where AccountId is not null. Limit Account results to 5 and Contact results to 10.


// APEX CODE
public with sharing class SearchService {

    @AuraEnabled(cacheable=true)
    public static Map<String, List<SObject>> searchByKeyword(
        String keyword) {

        // Guard against blank input
        if (String.isBlank(keyword)) {
            return new Map<String, List<SObject>>();
        }

        // Sanitize and append wildcard for prefix search
        String searchTerm =
            String.escapeSingleQuotes(keyword.trim()) + '*';

        // Run SOSL — bind variable used for the search term
        List<List<SObject>> results = [
            FIND :searchTerm
            IN ALL FIELDS
            RETURNING
                Account(Id, Name, Industry, Phone),
                Contact(Id, FirstName, LastName, Email, Phone)
            WITH USER_MODE
            LIMIT 100
        ];

        // Map results to named keys
        Map<String, List<SObject>> resultMap =
            new Map<String, List<SObject>>();
        resultMap.put('Accounts', results[0]);
        resultMap.put('Contacts', results[1]);

        return resultMap;
    }
}

Write a SOSL query to find all Contacts and Leads whose email address contains the domain “@techcorp.com”. Search only EMAIL FIELDS. Order Contact results by LastName ascending.


// APEX CODE
List<List<SObject>> results = [
    FIND '@techcorp.com'
    IN EMAIL FIELDS
    RETURNING
        Contact(Id, FirstName, LastName, Email
                ORDER BY LastName ASC),
        Lead(Id, FirstName, LastName, Email, Company)
];

List<Contact> contacts = (List<Contact>) results[0];
List<Lead>    leads    = (List<Lead>)    results[1];

System.debug('Contacts found: ' + contacts.size());
System.debug('Leads found: '    + leads.size());

Write a method secureSearch(String term) that searches for the term across Account and Contact using WITH USER_MODE. Wrap in try/catch — if a System.QueryException is thrown due to FLS restrictions, log the error and return an empty result map.


// APEX CODE
public with sharing class SecureSearchService {

    public static Map<String, List<SObject>> secureSearch(
        String term) {

        Map<String, List<SObject>> resultMap =
            new Map<String, List<SObject>>();

        if (String.isBlank(term)) return resultMap;

        String searchTerm =
            String.escapeSingleQuotes(term.trim()) + '*';

        try {
            List<List<SObject>> results = [
                FIND :searchTerm
                IN ALL FIELDS
                RETURNING
                    Account(Id, Name, AnnualRevenue, Industry),
                    Contact(Id, FirstName, LastName, Email)
                WITH USER_MODE
                LIMIT 50
            ];

            resultMap.put('Accounts', results[0]);
            resultMap.put('Contacts', results[1]);

        } catch (System.QueryException qe) {
            System.debug(
                'Security restriction: User lacks access. '
                + qe.getMessage()
            );
            // Return empty map — do not expose error to UI
        }

        return resultMap;
    }
}

Write a method dynamicObjectSearch(String keyword, String objectApiName, String fields) that builds and executes a dynamic SOSL query. The object name and field list are passed as parameters. Use Search.query() to execute. Sanitize all inputs.


// APEX CODE
public with sharing class DynamicSOSLService {

    public static List<List<SObject>> dynamicObjectSearch(
        String keyword,
        String objectApiName,
        String fields) {

        // Guard against blank inputs
        if (String.isBlank(keyword)
            || String.isBlank(objectApiName)
            || String.isBlank(fields)) {
            return new List<List<SObject>>();
        }

        // Sanitize all dynamic inputs
        String safeKeyword = String.escapeSingleQuotes(
            keyword.trim()) + '*';
        String safeObject  =
            String.escapeSingleQuotes(objectApiName.trim());
        String safeFields  =
            String.escapeSingleQuotes(fields.trim());

        // Build SOSL string dynamically
        String sosl =
            'FIND \''       + safeKeyword + '\''
            + ' IN ALL FIELDS'
            + ' RETURNING '  + safeObject
            + '('            + safeFields  + ')'
            + ' WITH USER_MODE'
            + ' LIMIT 50';

        try {
            // Execute dynamic SOSL
            return Search.query(sosl);
        } catch (System.SearchException se) {
            System.debug('SOSL Error: ' + se.getMessage());
            return new List<List<SObject>>();
        }
    }
}

ADVANCED SOSL PRACTICE QUESTIONS

Write a complete Apex method globalSearchSecure(String keyword) that searches across Account, Contact, and Opportunity. Use Security.stripInaccessible(AccessType.READABLE) on each object’s results before returning. Return a Map with object names as keys and sanitised lists as values.


// APEX CODE
public with sharing class GlobalSearchSecure {

    @AuraEnabled(cacheable=true)
    public static Map<String, List<SObject>> globalSearchSecure(
        String keyword) {

        Map<String, List<SObject>> resultMap =
            new Map<String, List<SObject>>();

        if (String.isBlank(keyword)) return resultMap;

        String searchTerm =
            String.escapeSingleQuotes(keyword.trim()) + '*';

        // Run SOSL without security enforcement first
        List<List<SObject>> rawResults = [
            FIND :searchTerm
            IN ALL FIELDS
            RETURNING
                Account(Id, Name, AnnualRevenue, SSN__c),
                Contact(Id, FirstName, LastName, Email, SSN__c),
                Opportunity(Id, Name, Amount, StageName)
            LIMIT 100
        ];

        // Strip inaccessible fields from each object's result
        SObjectAccessDecision accDecision =
            Security.stripInaccessible(
                AccessType.READABLE, rawResults[0]);
        SObjectAccessDecision conDecision =
            Security.stripInaccessible(
                AccessType.READABLE, rawResults[1]);
        SObjectAccessDecision oppDecision =
            Security.stripInaccessible(
                AccessType.READABLE, rawResults[2]);

        resultMap.put('Accounts',
            accDecision.getRecords());
        resultMap.put('Contacts',
            conDecision.getRecords());
        resultMap.put('Opportunities',
            oppDecision.getRecords());

        // Log which fields were stripped for audit
        System.debug('Stripped from Account: '
            + accDecision.getRemovedFields());
        System.debug('Stripped from Contact: '
            + conDecision.getRemovedFields());

        return resultMap;
    }
}

Write a method mergeAndTag(String keyword) that: (1) searches for the keyword across Account and Contact using SOSL, (2) tags all matching Accounts by setting Description = 'Search Match: ' + keyword, (3) performs a single bulkified DML update. Handle partial DML failures using Database.update(list, false) and log failures.


// APEX CODE
public with sharing class SearchAndTagService {

    public static void mergeAndTag(String keyword) {

        if (String.isBlank(keyword)) return;

        String searchTerm =
            String.escapeSingleQuotes(keyword.trim()) + '*';

        // Step 1 — SOSL to find matching records
        List<List<SObject>> results = [
            FIND :searchTerm
            IN ALL FIELDS
            RETURNING
                Account(Id, Name, Description)
            WITH USER_MODE
            LIMIT 200
        ];

        List<Account> matchedAccounts =
            (List<Account>) results[0];

        if (matchedAccounts.isEmpty()) {
            System.debug('No matching Accounts found.');
            return;
        }

        // Step 2 — Tag matching Accounts
        for (Account acc : matchedAccounts) {
            acc.Description =
                'Search Match: ' + keyword
                + ' | Tagged on: ' + Date.today();
        }

        // Step 3 — Bulkified DML with partial success
        Database.SaveResult[] saveResults =
            Database.update(matchedAccounts, false);

        // Step 4 — Log failures
        for (Integer i = 0; i < saveResults.size(); i++) {
            if (!saveResults[i].isSuccess()) {
                for (Database.Error err
                        : saveResults[i].getErrors()) {
                    System.debug(
                        'Failed: ' + matchedAccounts[i].Name
                        + ' | Error: ' + err.getMessage()
                    );
                }
            }
        }

        System.debug('Tagged '
            + matchedAccounts.size()
            + ' Accounts.');
    }
}

Build a complete solution: (1) Apex method search(String keyword) that returns Account and Contact results as a wrapper class SearchResult with @AuraEnabled fields. (2) LWC component globalSearch with a search input, Search button, and results displayed in two sections — Accounts and Contacts. Use imperative call on button click.


// ── APEX — SearchController.cls ──
public with sharing class SearchController {

    // Wrapper to send structured result to LWC
    public class SearchResult {
        @AuraEnabled public List<Account> accounts;
        @AuraEnabled public List<Contact> contacts;
        @AuraEnabled public Integer        totalCount;

        public SearchResult(
            List<Account> accs,
            List<Contact> cons) {
            this.accounts   = accs;
            this.contacts   = cons;
            this.totalCount = accs.size() + cons.size();
        }
    }

    @AuraEnabled
    public static SearchResult search(String keyword) {

        if (String.isBlank(keyword)) {
            return new SearchResult(
                new List<Account>(),
                new List<Contact>()
            );
        }

        String searchTerm =
            String.escapeSingleQuotes(keyword.trim()) + '*';

        List<List<SObject>> results = [
            FIND :searchTerm
            IN ALL FIELDS
            RETURNING
                Account(Id, Name, Industry, Phone),
                Contact(Id, FirstName, LastName, Email)
            WITH USER_MODE
            LIMIT 100
        ];

        return new SearchResult(
            (List<Account>) results[0],
            (List<Contact>) results[1]
        );
    }
}


<!-- globalSearch.html -->
<template>
    <lightning-card title="Global Search"
                    icon-name="utility:search">
        <div class="slds-m-around_medium">

            <lightning-input
                label="Search"
                placeholder="Type keyword and press Search..."
                value={keyword}
                onchange={handleKeywordChange}>
            </lightning-input>

            <lightning-button
                label="Search"
                variant="brand"
                class="slds-m-top_small"
                onclick={handleSearch}>
            </lightning-button>

            <template if:true={isLoading}>
                <lightning-spinner
                    alternative-text="Searching...">
                </lightning-spinner>
            </template>

            <template if:true={hasResults}>
                <p class="slds-m-top_medium">
                    <strong>Total results: {totalCount}</strong>
                </p>

                <h3 class="slds-m-top_medium">Accounts</h3>
                <template for:each={accounts} for:item="acc">
                    <div key={acc.Id}
                         class="slds-box slds-m-bottom_x-small">
                        <p><strong>{acc.Name}</strong></p>
                        <p>{acc.Industry} | {acc.Phone}</p>
                    </div>
                </template>

                <h3 class="slds-m-top_medium">Contacts</h3>
                <template for:each={contacts} for:item="con">
                    <div key={con.Id}
                         class="slds-box slds-m-bottom_x-small">
                        <p><strong>
                            {con.FirstName} {con.LastName}
                        </strong></p>
                        <p>{con.Email}</p>
                    </div>
                </template>
            </template>

            <template if:true={error}>
                <p class="slds-text-color_error">{error}</p>
            </template>

        </div>
    </lightning-card>
</template>


// globalSearch.js
import { LightningElement, track } from 'lwc';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import search from '@salesforce/apex/SearchController.search';

export default class GlobalSearch extends LightningElement {

    @track keyword    = '';
    @track accounts   = [];
    @track contacts   = [];
    @track totalCount = 0;
    @track isLoading  = false;
    @track error;

    get hasResults() {
        return this.totalCount > 0;
    }

    handleKeywordChange(event) {
        this.keyword = event.target.value;
    }

    handleSearch() {
        if (!this.keyword || this.keyword.trim().length < 2) {
            this.dispatchEvent(new ShowToastEvent({
                title:   'Validation',
                message: 'Please enter at least 2 characters',
                variant: 'warning'
            }));
            return;
        }

        this.isLoading = true;
        this.error     = undefined;

        search({ keyword: this.keyword })
            .then(result => {
                this.accounts   = result.accounts;
                this.contacts   = result.contacts;
                this.totalCount = result.totalCount;
                this.isLoading  = false;
            })
            .catch(error => {
                this.error     = error.body.message;
                this.isLoading = false;
            });
    }
}


<!-- globalSearch.js-meta.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle
    xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>59.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__AppPage</target>
        <target>lightning__HomePage</target>
    </targets>
</LightningComponentBundle>

Final Tip: SOSL is best remembered as “Google Search for Salesforce”. Use it when you don’t know which object has the data. Use SOQL when you know exactly where to look. Master the wildcard syntax, the IN search groups, and the List<List<SObject>> return type — those three concepts cover 90% of all SOSL interview questions.

I would recommend that you practise and revise the above theory and questions by writing manually on paper. It will help you remember the facts for a longer time than usual.

Was this Article helpful or not?

What can be improved?

What is the toughest Salesforce question asked in the interview from you and what is the one toughest challenge you have faced during your work. Kindly let us know your thoughts in the comments and lets discuss.

Coming Next

Salesforce Database Method Cheatsheet and Interview Questions

Subscribe to us on these platforms.

Subscribe to us to not miss important updates and posts and to get the latest information.

About the Author

Ashish is a Salesforce Developer specializing in Apex, Lightning Web Components (LWC), Integrations, Flows, SOQL, SOSL, and Salesforce Architecture. He regularly publishes Salesforce interview questions, scenario-based tutorials, cheat sheets, and hands-on development guides designed to help developers and administrators succeed in real-world projects and technical interviews.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *