Salesforce Developer · Session 72

SOSL in Salesforce: Salesforce Object Search Language Explained

By Himanshu Gupta June 17, 2026 12 min read

SOSL (Salesforce Object Search Language) is a search language that queries Salesforce's full-text search index to find records across multiple objects in a single statement. Unlike SOQL, which queries one object at a time, a single SOSL statement can return matching Accounts, Contacts, Opportunities, and custom objects simultaneously — without knowing which object a search term lives in.

SOSL vs SOQL: The Fundamental Difference

SOQL and SOSL solve different problems. Understanding which to use requires understanding how Salesforce stores and retrieves data.

SOQLSOSL
What it queriesDatabase fields on one objectFull-text search index across objects
Objects per queryOne (plus joins via relationships)Multiple simultaneously
Best forStructured data retrieval with known filtersSearch-style queries across objects
Requires knowing objectYesNo
Supports wildcardLimited (LIKE operator)Yes (*, ?)
Min search term lengthNo minimum2 characters
Return type in ApexList<SObject>List<List<SObject>>

The return type difference is the most common source of SOSL bugs. SOSL returns a List of Lists — one inner list per object in the RETURNING clause. You must index into the outer list to access each object's results.

Basic SOSL Syntax

The minimal SOSL statement has three components: the FIND clause, the search group, and the RETURNING clause.

// Minimal SOSL
List<List<SObject>> results = [
  FIND 'Acme'
  IN ALL FIELDS
  RETURNING Account(Id, Name), Contact(Id, FirstName, LastName)
];

The FIND clause contains the search term. The search group (IN ALL FIELDS) determines which fields are searched. The RETURNING clause lists the objects to return results from, with optional field selection.

// Accessing the results — one List per RETURNING object
List<Account> accounts = (List<Account>) results[0];
List<Contact> contacts = (List<Contact>) results[1];

The Four Search Groups

The search group controls which fields the search index scans. Narrowing the search group improves performance.

Search GroupFields SearchedWhen to Use
ALL FIELDSText, phone, email, URL fieldsGeneral search — widest coverage
NAME FIELDSName fields onlyLooking for a specific record name — fastest
EMAIL FIELDSEmail fields onlyEmail-specific lookup
PHONE FIELDSPhone fields onlyPhone-specific lookup
// Fastest lookup when searching by name
[FIND 'Acme' IN NAME FIELDS RETURNING Account(Id, Name)]

// Email-specific search
[FIND '[email protected]' IN EMAIL FIELDS
  RETURNING Contact(Id, FirstName, LastName, Email)]

Wildcards in SOSL

SOSL supports two wildcard characters. These work inside the FIND clause search term and allow partial matching.

// Prefix wildcard — finds anything starting with 'sf'
[FIND 'sf*' IN ALL FIELDS RETURNING Account]

// Wildcards only work at end of terms, not start
// '*force' is NOT supported — would need SOQL LIKE '%force%'

Wildcards cannot appear at the beginning of a search term. '*force' is invalid. Use SOQL's LIKE operator with a leading % when you need suffix or infix matching.

The RETURNING Clause in Detail

The RETURNING clause accepts standard SOQL-style clauses per object: field selection, WHERE, ORDER BY, and LIMIT.

List<List<SObject>> results = [
  FIND 'tech*'
  IN ALL FIELDS
  RETURNING
    Account(
      Id, Name, Industry, AnnualRevenue
      WHERE IsActive__c = true
      ORDER BY AnnualRevenue DESC
      LIMIT 10
    ),
    Contact(
      Id, FirstName, LastName, Email
      WHERE Department = 'Engineering'
    )
];

The WHERE clause in RETURNING filters within the search results — it does not affect what SOSL searches. SOSL finds matching records first; WHERE then filters that result set.

SOSL Governor Limits

SOSL shares the 100-query-per-transaction limit with SOQL. Additional SOSL-specific limits:

// AND/OR within SOSL search term
[FIND 'Acme OR Salesforce' IN NAME FIELDS
  RETURNING Account]

[FIND 'Acme AND Technologies' IN ALL FIELDS
  RETURNING Account]

Dynamic SOSL

When the search term comes from user input, build the SOSL string dynamically using Search.query() instead of a static literal. This avoids injection risks and allows runtime construction.

String searchTerm = 'Acme*'; // from user input
// Escape special characters before interpolating
String escaped = String.escapeSingleQuotes(searchTerm);

List<List<SObject>> results = Search.query(
  'FIND \'' + escaped + '\' IN ALL FIELDS ' +
  'RETURNING Account(Id, Name)'
);

Never interpolate unsanitised user input directly into a SOSL string. Use String.escapeSingleQuotes() before injecting user-provided search terms into dynamic SOSL.

SOSL Without a RETURNING Clause

Omitting RETURNING causes SOSL to search all searchable objects and return Id and Name only. This is rarely what you want in production code — it can return thousands of records from unexpected objects.

// Avoid in production — returns everything from all searchable objects
[FIND 'Acme' IN ALL FIELDS]

// Always specify RETURNING in production code
[FIND 'Acme' IN ALL FIELDS
  RETURNING Account(Id, Name), Contact(Id, Name)]

Practical Pattern: Global Search Handler

The canonical use case for SOSL is a global search feature where a user types a term and the UI should return matching records across object types.

public class GlobalSearchController {
  public static Map<String,List<SObject>> search(String term) {
    Map<String,List<SObject>> resultMap = new Map<String,List<SObject>>();

    // Minimum 2 chars required
    if (String.isBlank(term) || term.length() < 2) return resultMap;

    String escaped = String.escapeSingleQuotes(term + '*');

    List<List<SObject>> raw = Search.query(
      'FIND \'' + escaped + '\' IN ALL FIELDS ' +
      'RETURNING ' +
      'Account(Id, Name LIMIT 5), ' +
      'Contact(Id, FirstName, LastName LIMIT 5), ' +
      'Opportunity(Id, Name LIMIT 5)'
    );

    resultMap.put('accounts', raw[0]);
    resultMap.put('contacts', raw[1]);
    resultMap.put('opportunities', raw[2]);

    return resultMap;
  }
}

SOSL in Test Classes

SOSL in test methods does not use the real search index — it returns empty results unless you explicitly seed the test data using Test.setFixedSearchResults().

@isTest
static void testSearch() {
  Account a = new Account(Name = 'Acme Technologies');
  insert a;

  // Tell the test framework what SOSL should return
  Test.setFixedSearchResults(new List<Id>{ a.Id });

  List<List<SObject>> results = [
    FIND 'Acme' IN ALL FIELDS RETURNING Account
  ];

  System.assertEquals(1, results[0].size());
}

Forgetting Test.setFixedSearchResults() is the most common cause of SOSL tests passing with zero assertions. Always seed the search results explicitly in test context.

When to Use SOSL — The Decision Rule

Use SOSL when:

Use SOQL when:

Related: SOQL Aggregate Functions covers how to aggregate SOQL results with COUNT, SUM, AVG, MIN, MAX, and GROUP BY — the complement to SOSL for structured data retrieval.

Frequently Asked Questions

What is SOSL in Salesforce?
SOSL (Salesforce Object Search Language) is a search language that queries Salesforce's full-text search index to find records across multiple objects simultaneously. Unlike SOQL, which queries one object at a time using a database index, SOSL can return matching Accounts, Contacts, Opportunities, and custom objects in a single statement.
When should I use SOSL instead of SOQL?
Use SOSL when you don't know which object a search term will be found in, or when you need to search across multiple objects simultaneously. Use SOQL when you know the specific object and want to filter by specific fields. SOSL is ideal for global search functionality; SOQL is ideal for structured data retrieval with known filters.
What are the SOSL search groups?
SOSL has four search groups: ALL FIELDS (searches all text, phone, email, and URL fields), NAME FIELDS (searches only name fields — fastest), EMAIL FIELDS (searches only email fields), PHONE FIELDS (searches only phone fields). ALL FIELDS is the default when no group is specified.
What is the RETURNING clause in SOSL?
The RETURNING clause specifies which objects and fields to return from the search. You list each object with optional field selection and WHERE/ORDER BY/LIMIT clauses. Without RETURNING, SOSL returns Id and Name from all searchable objects. Each object in RETURNING produces a separate inner List in the results.
What are the governor limits for SOSL?
SOSL queries count towards the 100 SOQL/SOSL queries per transaction limit. SOSL returns a maximum of 2,000 records per query (200 per object by default). Each object in RETURNING has a default limit of 200 records, overridable with LIMIT. SOSL requires a minimum search term of 2 characters.