Skip to main content

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 SelectedResponse SizeTransfer 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:

  1. Always use $select for list views
  2. Include primary key in selection
  3. Select only fields you render
  4. Combine with pagination for best performance
  5. Especially important for mobile apps

Next: Pagination → to learn efficient data pagination.