* Migrating Core Salesforce Skills * Updating pr comments * updat reference * Updating a skill * Migrating Datacloud skills * Migrating Industries cloud skills * Validating - skills fixing --------- Co-authored-by: Sandip Kumar Yadav <sandipkumar.yadav+sfemu@salesforce.com>
7.4 KiB
Data Mapper Best Practices
When to Use Each Type
Extract
Use Extract when:
- Reading data from one or more related Salesforce objects
- You need relationship queries (parent-to-child or child-to-parent)
- Formula fields are required in the output
- Data volume is moderate (under 10K records per execution)
- You need aggregate functions or complex filter logic
Do NOT use Extract when:
- Read volume exceeds 10K records consistently -- use Turbo Extract
- No SOQL is needed (data reshaping only) -- use Transform
- You are writing data -- use Load
Turbo Extract
Use Turbo Extract when:
- Read-heavy scenarios with high volume (10K+ records)
- Query is straightforward with indexed filter fields
- Formula fields are not required
- No related list (child-to-parent) queries are needed
- Performance is the primary concern (10x+ faster than standard Extract)
Do NOT use Turbo Extract when:
- Formula fields are needed in output
- Related list queries are required
- Aggregate queries (COUNT, SUM) are needed
- Polymorphic lookup fields are involved
Transform
Use Transform when:
- Reshaping JSON structures between Integration Procedure steps
- Renaming fields from one schema to another
- Flattening nested data structures
- Filtering or merging in-memory datasets
- No database interaction is needed
Do NOT use Transform when:
- Reading from or writing to Salesforce objects -- use Extract or Load
- Data needs to be persisted -- use Load
Load
Use Load when:
- Inserting, updating, upserting, or deleting Salesforce records
- Writing data collected from OmniScript input or external sources
- Synchronizing data from Integration Procedure callout responses
Do NOT use Load when:
- Reading data -- use Extract or Turbo Extract
- Reshaping data without persistence -- use Transform
Field Mapping Patterns
Explicit Field Selection
Always specify fields explicitly. Never rely on wildcard or "all fields" selection.
Good: Account.Name, Account.Industry, Account.BillingCity
Bad: Account.* (extracts all fields, wastes bandwidth and heap)
Input/Output Path Structure
Data Mapper fields use dot-notation paths for input and output:
Input Path: AccountData.Name
Output Path: Account.Name
For nested structures:
Input Path: Response.data.accounts[0].name
Output Path: AccountList.Name
Type Conversion Handling
Map fields with compatible types. Common conversions:
| Source Type | Target Type | Notes |
|---|---|---|
| String | Date | Requires ISO 8601 format (YYYY-MM-DD) |
| String | Number | Ensure source contains numeric values only |
| Boolean | String | Maps to "true"/"false" string literals |
| DateTime | Date | Truncates time component |
| Picklist | String | Maps selected value as string |
Lookup Resolution for Load
When loading records with lookup relationships:
- Define a lookup mapping that resolves the external key to a Salesforce ID
- Specify the lookup object and match field (e.g.,
Account.Nameto resolveAccountId) - Handle cases where the lookup returns no match (set default or fail gracefully)
Field: AccountId
Lookup Object: Account
Match Field: Name
Input Path: InputData.AccountName
Query Sequence Optimization
Filter Field Indexing
For Extract and Turbo Extract, filter on indexed fields whenever possible:
Id(always indexed)Name(indexed on standard objects)CreatedDate(indexed)SystemModstamp(indexed)- Custom fields marked as External ID or Unique
- Custom Index fields (request from admin if needed)
Filter Order
Place the most selective filter first to reduce the result set early:
Good: WHERE Id = :recordId AND Status = 'Active'
Bad: WHERE Status = 'Active' AND Id = :recordId
Relationship Query Depth
Limit relationship traversal to 2 levels for performance:
Good: Account.Owner.Name (1 level)
Bad: Account.Parent.Parent.Parent.Owner.Name (3+ levels)
Limit and Offset
Always set a LIMIT on Extract queries unless the consuming component guarantees a bounded input:
LIMIT 200 -- Standard batch size
LIMIT 2000 -- Maximum for most UI scenarios
LIMIT 10000 -- Absolute maximum, use only with pagination
Null Handling and Type Conversion
Default Values
Set default values for fields that may be null to prevent downstream errors:
| Field Type | Recommended Default | Rationale |
|---|---|---|
| String | "" (empty string) |
Prevents null reference in concatenation |
| Number | 0 |
Prevents null arithmetic errors |
| Boolean | false |
Prevents null conditional evaluation |
| Date | (no default) | Leave null; do not fabricate dates |
| Lookup | (no default) | Leave null; handle in consuming component |
Null-Safe Mapping
When mapping fields that may be null:
- Set
isNullable: trueon the OmniDataTransformItem - Configure a default value where business logic requires one
- Document which fields are expected to be null in certain scenarios
- Test with records that have null values in mapped fields
Relationship Queries
Parent-to-Child (Subquery)
Extract supports parent-to-child relationship queries:
Object: Account
Fields: Name, Industry
Child Relationship: Contacts (Contact)
Child Fields: FirstName, LastName, Email
Output structure:
{
"Name": "Acme Corp",
"Industry": "Technology",
"Contacts": [
{ "FirstName": "Jane", "LastName": "Doe", "Email": "jane@acme.com" }
]
}
Child-to-Parent (Lookup Traversal)
Extract supports child-to-parent traversal via dot notation:
Object: Contact
Fields: FirstName, LastName, Account.Name, Account.Industry
Output structure:
{
"FirstName": "Jane",
"LastName": "Doe",
"AccountName": "Acme Corp",
"AccountIndustry": "Technology"
}
Turbo Extract Limitations
Turbo Extract does NOT support:
- Child-to-parent relationship queries (subqueries)
- Formula fields
- Aggregate functions
- Polymorphic lookups (e.g.,
WhoIdon Task)
Performance with Large Data Volumes
Batch Size Recommendations
| Record Count | Recommended Approach |
|---|---|
| 1-200 | Standard Extract, single call |
| 200-2000 | Turbo Extract, single call |
| 2000-10000 | Turbo Extract with pagination via Integration Procedure |
| 10000+ | Batch processing: scheduled Integration Procedure with chunked Turbo Extract calls |
Heap Size Management
Each Data Mapper execution contributes to the Apex heap limit (6 MB synchronous, 12 MB async):
- Map only the fields you need (reduces JSON payload size)
- Use Turbo Extract for large result sets (server-side processing reduces heap usage)
- Paginate results when total data exceeds 2 MB
Caching Strategy
For data that changes infrequently:
- Enable Platform Cache in the consuming Integration Procedure
- Set appropriate TTL (Time To Live) based on data change frequency
- Cache at the org partition level for shared reference data
- Cache at the session partition level for user-specific data
Monitoring
Track Data Mapper performance using:
sf data query -q "SELECT Id,Name,Type,LastModifiedDate FROM OmniDataTransform WHERE IsActive=true ORDER BY LastModifiedDate DESC" -o <org>
Review execution logs in OmniStudio Designer > Data Mapper > Preview to identify slow queries and excessive field counts.