Field Projection
Overview
Field projection uses the $select parameter to specify exactly which fields to return in the response. This is one of the most important performance optimizations available in Core APIs.
Benefits:
- Reduces response size (faster network transfer)
- Reduces database I/O (fewer columns read)
- Reduces JSON serialization overhead
- Improves client-side rendering performance
Basic Field Selection
Select Specific Fields
Request only ID, name, and price:
GET /api/v4/core/PRD?source=productList&\
$select=PRD_ID,XPRD01,XPRD02
Without $select (default - all visible fields):
{
"data": [
{
"PRD_ID": 123,
"XPRD01": "Widget Pro",
"XPRD02": 49.99,
"XPRD03": "PRD-2025-001",
"XPRD04": "Long description...",
"XPRD05": "Electronics",
"XPRD06": true,
"XPRD30": false,
"XPRD36": 2.5,
// ... 40+ more fields
"OWNER": "user123",
"CDATA": "20251201143000",
"LDATA": "20251215093000",
"TREC": "N"
}
]
}
With $select (only 3 fields):
{
"data": [
{
"PRD_ID": 123,
"XPRD01": "Widget Pro",
"XPRD02": 49.99
}
]
}
Response size reduction: ~95% smaller (50 fields → 3 fields).
Always Include Primary Key
Best practice:
# ✅ Good - includes primary key
$select=PRD_ID,XPRD01,XPRD02
# ❌ Problematic - missing primary key
$select=XPRD01,XPRD02
Why primary key matters:
- Detail view navigation:
GET /api/v4/core/PRD/{PRD_ID} - Update operations:
PUT /api/v4/core/PRD/{PRD_ID} - Delete operations:
DELETE /api/v4/core/PRD/{PRD_ID} - Client-side state management (React keys, Vue refs)
- Avoiding duplicate records in UI
Performance Impact
Response Size Comparison
Scenario: Product list with 100 records
| Fields Selected | Response Size | Transfer Time (3G) | Transfer Time (4G) |
|---|---|---|---|
| All (50 fields) | ~500 KB | ~2.5 seconds | ~0.8 seconds |
| 10 fields | ~100 KB | ~0.5 seconds | ~0.15 seconds |
| 3 fields | ~30 KB | ~0.15 seconds | ~0.05 seconds |
Impact: 10x-17x faster response with field projection.
Database Performance
Without $select:
SELECT * FROM TB_ANAG_PRD00
WHERE ...
- Reads 50+ columns from disk
- Loads unnecessary data into memory
- Increases I/O wait time
With $select:
SELECT PRD_ID, XPRD01, XPRD02 FROM TB_ANAG_PRD00
WHERE ...
- Reads only 3 columns from disk
- Minimal memory usage
- Faster query execution
Use Cases
List Views
Product grid - show only essentials:
GET /api/v4/core/PRD?source=productList&\
$select=PRD_ID,XPRD01,XPRD02,XPRD12&\
$num_rows=25
Response: Perfect for rendering product cards with name, price, image.
Autocomplete/Search
Type-ahead search - minimal data:
GET /api/v4/core/PRD?source=productSearch&\
$filter=startwith(XPRD01,'Wid')&\
$select=PRD_ID,XPRD01&\
$num_rows=10
Response: Only ID and name for fast autocomplete.
Data Export
CSV export - select export columns:
GET /api/v4/export/PRD?source=productExport&\
$select=XPRD03,XPRD01,XPRD02,XPRD05&\
$order=XPRD03 ASC
Response: Only fields needed in CSV (code, name, price, category).
Mobile Apps
Minimize bandwidth for mobile:
GET /api/v4/core/PRD?source=mobileProductList&\
$select=PRD_ID,XPRD01,XPRD02,XPRD37&\
$num_rows=20
Why: Mobile networks slower + data caps make field projection critical.
Combining with Other Parameters
Field Selection + Filter
GET /api/v4/core/PRD?source=productList&\
$filter=XPRD06 eq true&\
$select=PRD_ID,XPRD01,XPRD02
Field Selection + Sort
GET /api/v4/core/PRD?source=productList&\
$select=PRD_ID,XPRD01,XPRD02&\
$order=XPRD02 DESC
Note: You can sort by fields NOT in $select.
Field Selection + Pagination
GET /api/v4/core/PRD?source=productList&\
$select=PRD_ID,XPRD01,XPRD02&\
$num_rows=25&\
$offset=50
Complete Query
GET /api/v4/core/PRD?source=productList&\
$filter=XPRD05 eq 'Electronics' AND XPRD06 eq true&\
$select=PRD_ID,XPRD01,XPRD02,XPRD03&\
$order=XPRD02 DESC&\
$num_rows=25&\
$offset=0
Field Visibility and COD_ON_OFF
$select Respects COD_ON_OFF
Important: You can only select fields visible in the current context.
# Context: center_dett=visualizza (list view)
GET /api/v4/core/PRD?source=productList&\
center_dett=visualizza&\
$select=PRD_ID,XPRD01,XPRD38
If XPRD38 has COD_ON_OFF='D' (detail only):
{
"data": [
{
"PRD_ID": 123,
"XPRD01": "Widget Pro"
// XPRD38 not included (no 'L' flag)
}
]
}
Field silently omitted - no error, just excluded.
peso Filtering
Fields filtered by peso (COD_UTENTE):
GET /api/v4/core/PRD?source=productList&\
$select=PRD_ID,XPRD01,XPRD_COST
If XPRD_COST requires peso >= 50 and user has peso = 30:
{
"data": [
{
"PRD_ID": 123,
"XPRD01": "Widget Pro"
// XPRD_COST excluded (peso insufficient)
}
]
}
JavaScript Implementation
Simple Field Selector
class QueryBuilder {
constructor(dimension, source) {
this.dimension = dimension;
this.source = source;
this.fields = [];
this.filters = [];
}
select(...fields) {
this.fields = fields;
return this;
}
filter(condition) {
this.filters.push(condition);
return this;
}
buildUrl(apiBase) {
const url = new URL(`${apiBase}/api/v4/core/${this.dimension}`);
url.searchParams.append('source', this.source);
if (this.fields.length) {
url.searchParams.append('$select', this.fields.join(','));
}
if (this.filters.length) {
url.searchParams.append('$filter', this.filters.join(' AND '));
}
return url;
}
}
// Usage
const query = new QueryBuilder('PRD', 'productList')
.select('PRD_ID', 'XPRD01', 'XPRD02')
.filter('XPRD06 eq true')
.buildUrl(apiBase);
const response = await fetch(query, {
headers: { 'Authorization': `Bearer ${token}` }
});
Dynamic Field Selection
function buildProductListQuery(options = {}) {
const baseFields = ['PRD_ID', 'XPRD01']; // Always include ID and name
const fields = [...baseFields];
// Add optional fields based on view type
if (options.showPrice) {
fields.push('XPRD02');
}
if (options.showImage) {
fields.push('XPRD12');
}
if (options.showCategory) {
fields.push('XPRD05');
}
if (options.showStock) {
fields.push('XPRD09');
}
const url = new URL(`${apiBase}/api/v4/core/PRD`);
url.searchParams.append('source', 'productList');
url.searchParams.append('$select', fields.join(','));
return url;
}
// Usage
const listViewUrl = buildProductListQuery({
showPrice: true,
showImage: true
});
// $select=PRD_ID,XPRD01,XPRD02,XPRD12
const minimalUrl = buildProductListQuery({});
// $select=PRD_ID,XPRD01
Best Practices
✅ DO:
Always use $select for list views:
# ✅ Good
$select=PRD_ID,XPRD01,XPRD02
Include primary key:
# ✅ Good
$select=PRD_ID,XPRD01
Select only what you render:
// ✅ Good - rendering name and price
$select=PRD_ID,XPRD01,XPRD02
// ❌ Bad - fetching description you don't use
$select=PRD_ID,XPRD01,XPRD02,XPRD04
Use narrow selections for mobile:
# ✅ Good for mobile
$select=PRD_ID,XPRD01,XPRD37
❌ DON'T:
Don't fetch all fields by default:
# ❌ Bad - 500KB response
GET /api/v4/core/PRD?source=productList
# ✅ Good - 30KB response
GET /api/v4/core/PRD?source=productList&$select=PRD_ID,XPRD01,XPRD02
Don't select fields you don't use:
# ❌ Bad - fetching 20 fields but only displaying 3
$select=PRD_ID,XPRD01,XPRD02,...,XPRD20
Don't forget primary key:
# ❌ Bad - can't navigate to detail
$select=XPRD01,XPRD02
# ✅ Good
$select=PRD_ID,XPRD01,XPRD02
Common Mistakes
Mistake 1: Selecting Hidden Fields
# ❌ Won't work - TIMESTAMP has COD_ON_OFF='X' (hidden)
$select=PRD_ID,XPRD01,TIMESTAMP
# Response: { "PRD_ID": 123, "XPRD01": "Widget" }
# TIMESTAMP silently excluded
Mistake 2: Sorting by Non-Selected Field
This is valid:
# ✅ Valid - can sort by field not in $select
$select=PRD_ID,XPRD01&$order=XPRD02 DESC
Response:
{
"data": [
{"PRD_ID": 456, "XPRD01": "Premium Widget"},
{"PRD_ID": 123, "XPRD01": "Standard Widget"}
]
}
Sorted by XPRD02 but XPRD02 not included in response.
Mistake 3: Spaces in $select
# ❌ Wrong - spaces not allowed
$select=PRD_ID, XPRD01, XPRD02
# ✅ Correct - no spaces
$select=PRD_ID,XPRD01,XPRD02
Summary
Field projection with $select is essential for performance:
- ✅ Reduces response size by 80-95%
- ✅ Speeds up database queries
- ✅ Critical for mobile apps and slow networks
- ✅ Improves client-side rendering
- ✅ Respects COD_ON_OFF and peso filtering
Key Takeaways:
- Always use
$selectfor list views - Include primary key in selection
- Select only fields you render
- Combine with pagination for best performance
- Especially important for mobile apps
Next: Pagination → to learn efficient data pagination.
Related Concepts
- Basic Queries - Query fundamentals
- Field Visibility - COD_ON_OFF bitmask
- Query Performance - Performance optimization