Field selection allows you to specify exactly which fields to return in your API responses. This reduces payload size, improves performance, and gives clients fine-grained control over the data they receive.
Basic Syntax
The fields parameter uses the following format:
fields = { field1}, {field2} , {field3}
fields : Comma-separated list of field names to return
Aliases
The fields parameter has aliases:
# Both are equivalent
GET /users?fields=id,name,email
GET /users?select=id,name,email
Basic Usage
Single Field
# Return only the name field
GET /users?fields=name
Multiple Fields
# Return id, name, and email fields
GET /users?fields=id,name,email
Fields are separated by commas (,) with no spaces.
Default Behavior
Without field selection, all fields are returned:
# Returns all fields
GET /users/1
# Response:
{
"id" : 1,
"name" : "John Doe",
"email" : "john@example.com",
"age" : 30,
"isActive" : true ,
"createdAt" : "2024-01-01T00:00:00.000Z",
"updatedAt" : "2024-01-15T00:00:00.000Z"
}
With field selection:
# Returns only selected fields
GET /users/1?fields=id,name,email
# Response:
{
"id" : 1,
"name" : "John Doe",
"email" : "john@example.com"
}
Common Use Cases
Minimal Data for Lists
# User list with minimal data
GET /users?fields=id,name,avatar & limit = 50
Perfect for rendering user lists where you only need basic info.
ID and Name for Dropdowns
# For select/dropdown components
GET /categories?fields=id,name
GET /users?fields=id,name
GET /products?fields=id,title
Excluding Sensitive Fields
# Public profile (exclude sensitive data)
GET /users?fields=id,name,bio,avatar
# Excludes: email, phone, address, etc.
Mobile API Responses
# Lightweight response for mobile
GET /posts?fields=id,title,excerpt,thumbnail & limit = 20
# Excludes: full content, author details, etc.
Field Selection with Relations
Combine field selection with joins:
# Select fields from main entity
GET /posts?fields=id,title,content & join = author
# Select fields from both main and related entities
GET /posts?fields=id,title,content & join = author || name,email
Main Entity Fields
The fields parameter controls the main entity fields:
GET /posts?fields=id,title & join = author || name,email
Returns:
{
"id" : 1 ,
"title" : "My Post" ,
"author" : {
"name" : "John Doe" ,
"email" : "john@example.com"
}
}
Use the join syntax to select related entity fields:
join = { relation} || {field1},{field2}
# Select specific fields from author
GET /posts?join=author || name,avatar
# Select from multiple relations
GET /posts?join=author || name & join = category || name
Nested Field Selection
For nested relations, use dot notation in field names:
# Select nested fields
GET /users?fields=id,name,profile.city,profile.country
# Or use join with field selection
GET /users?fields=id,name & join = profile || city,country
Using join syntax is generally more explicit and recommended for selecting related entity fields.
Complete Examples
User Profile API
# Public profile
GET /users/123?fields=id,name,bio,avatar,createdAt
# Profile with location
GET /users/123?fields=id,name,email & join = profile || city,country
# Minimal user info
GET /users?fields=id,name & limit = 100
Blog API
# Post list with preview
GET /posts?fields=id,title,excerpt,thumbnail,publishedAt & limit = 20
# Full post with author
GET /posts/456?fields=id,title,content,publishedAt & join = author || name,avatar
# Post titles only
GET /posts?fields=id,title & sort = publishedAt,DESC
E-commerce API
# Product list
GET /products?fields=id,name,price,thumbnail,inStock & limit = 50
# Product details
GET /products/789?fields=id,name,description,price,sku & join = category || name
# Minimal product info for cart
GET /products?fields=id,name,price & filter = id || in || 1,2,3
Combining with Other Parameters
With Filtering
GET /users?filter=isActive || eq || true & fields = id,name,email
With Sorting
GET /products?sort=price,ASC & fields = id,name,price
GET /users?limit= 20 & page = 1 & fields = id,name,email & sort = name,ASC
Complete Query
GET /posts?filter=status || eq || published & filter = category || eq || Technology & fields = id,title,excerpt & join = author || name,avatar & sort = publishedAt,DESC & limit = 20 & page = 1
This request:
Filters published posts in Technology category
Returns only id, title, and excerpt from posts
Joins author with name and avatar
Sorts by publish date (newest first)
Returns 20 posts per page
Returns first page
Reduced Payload Size
# ❌ Bad: Returns all fields (large response)
GET /users?limit= 1000
# Response size: ~500KB
# ✅ Good: Returns only needed fields
GET /users?fields=id,name & limit = 1000
# Response size: ~50KB (10x smaller)
Faster Database Queries
Selecting fewer fields can improve database query performance:
# ❌ Bad: SELECT * FROM users
GET /users
# ✅ Good: SELECT id, name, email FROM users
GET /users?fields=id,name,email
Reduced Network Transfer
# Mobile app: Only load essential data
GET /posts?fields=id,title,thumbnail & limit = 20
Especially important for mobile apps on slow connections.
Security Considerations
Protecting Sensitive Fields
Configure which fields can be selected:
import { Crud } from '@nestjsx/crud' ;
@ Crud ({
model: { type: User },
query: {
exclude: [ 'password' , 'passwordResetToken' ], // Never allow these
},
})
@ Controller ( 'users' )
export class UsersController {}
Field Whitelisting
@ Crud ({
model: { type: User },
query: {
allow: [ 'id' , 'name' , 'email' , 'avatar' ], // Only allow these fields
},
})
Always use exclude or allow in your CRUD configuration to prevent exposure of sensitive fields like passwords, tokens, or internal IDs.
Entity Configuration
TypeORM Example
import { Entity , Column , PrimaryGeneratedColumn } from 'typeorm' ;
import { Exclude } from 'class-transformer' ;
@ Entity ()
export class User {
@ PrimaryGeneratedColumn ()
id : number ;
@ Column ()
name : string ;
@ Column ()
email : string ;
@ Column ()
@ Exclude () // Never include in responses
password : string ;
@ Column ()
avatar : string ;
@ Column ()
bio : string ;
}
Controller Configuration
import { Crud , CrudController } from '@nestjsx/crud' ;
import { Controller } from '@nestjs/common' ;
import { UsersService } from './users.service' ;
import { User } from './user.entity' ;
@ Crud ({
model: {
type: User ,
},
query: {
exclude: [ 'password' ], // Never return password
allow: [ 'id' , 'name' , 'email' , 'avatar' , 'bio' , 'createdAt' ], // Allowed fields
},
})
@ Controller ( 'users' )
export class UsersController implements CrudController < User > {
constructor ( public service : UsersService ) {}
}
Frontend Implementation
React Example
import { useState , useEffect } from 'react' ;
function UserList () {
const [ users , setUsers ] = useState ([]);
useEffect (() => {
// Only fetch fields needed for the list
fetch ( '/api/users?fields=id,name,avatar&limit=50' )
. then ( res => res . json ())
. then ( data => setUsers ( data ));
}, []);
return (
< div >
{ users . map ( user => (
< div key = { user . id } >
< img src = { user . avatar } alt = { user . name } />
< span > { user . name } </ span >
</ div >
)) }
</ div >
);
}
JavaScript with RequestQueryBuilder
import { RequestQueryBuilder } from '@nestjsx/crud-request' ;
// Select specific fields
const query = RequestQueryBuilder . create ()
. select ([ 'id' , 'name' , 'email' ])
. query ();
// Result: fields=id,name,email
fetch ( `/api/users? ${ query } ` );
TypeScript Example
import { RequestQueryBuilder } from '@nestjsx/crud-request' ;
interface UserListItem {
id : number ;
name : string ;
avatar : string ;
}
async function fetchUsers () : Promise < UserListItem []> {
const query = RequestQueryBuilder . create ()
. select ([ 'id' , 'name' , 'avatar' ])
. setLimit ( 50 )
. sortBy ({ field: 'name' , order: 'ASC' })
. query ();
const response = await fetch ( `/api/users? ${ query } ` );
return response . json ();
}
Common Patterns
Dropdown/Select Options
GET /categories?fields=id,name & sort = name,ASC
GET /users?fields=id,name & filter = isActive || eq || true
Search Results
GET /products?fields=id,name,price,thumbnail & filter = name || cont || laptop & limit = 10
Table/Grid Display
GET /users?fields=id,name,email,status,createdAt & limit = 50 & sort = createdAt,DESC
Card/Preview Display
GET /posts?fields=id,title,excerpt,thumbnail,author & join = author || name & limit = 12
Autocomplete
GET /users?fields=id,name & filter = name || starts || Jo & limit = 10
Validation and Errors
Invalid field parameters will be handled according to your configuration:
# If 'secretField' is not in the allow list or is in exclude list
GET /users?fields=id,name,secretField
# The secretField will be ignored or throw an error
// Configure strict validation
@ Crud ({
model: { type: User },
query: {
allow: [ 'id' , 'name' , 'email' ],
// Any other field will be rejected
},
})
Best Practices
Always select only needed fields : Don’t default to selecting all fields
Configure field access : Use exclude or allow in your controller
Protect sensitive data : Never expose passwords, tokens, or internal fields
Use TypeScript : Define interfaces for different field selections
Document available fields : Clearly document which fields are available
Consider mobile clients : Select minimal fields for mobile endpoints
Test performance : Measure the impact of field selection on performance
Use consistent naming : Keep field names consistent across your API
GraphQL-Like Queries
While not as flexible as GraphQL, field selection provides similar benefits:
# Similar to GraphQL query:
# query {
# users {
# id
# name
# profile { city }
# }
# }
GET /users?fields=id,name & join = profile || city
Advanced Examples
Multi-Level Field Selection
# Select fields from nested relations
GET /users?fields=id,name & join = posts || id,title & join = posts.comments || text
Dynamic Field Selection
// Allow users to choose fields
function fetchData ( selectedFields ) {
const fields = selectedFields . join ( ',' );
return fetch ( `/api/users?fields= ${ fields } ` );
}
// Usage
fetchData ([ 'id' , 'name' , 'email' ]);
Conditional Field Loading
// Load more fields when viewing details
const listFields = 'id,name,avatar' ;
const detailFields = 'id,name,email,bio,createdAt,updatedAt' ;
// List view
fetch ( `/api/users?fields= ${ listFields } ` );
// Detail view
fetch ( `/api/users/123?fields= ${ detailFields } ` );
Next Steps
Relations Select fields from related entities
Filtering Filter results before selecting fields
Pagination Paginate through selected fields
Query Parameters Overview of all query parameters