Skip to main content
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:
  • fields
  • select
# 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": "[email protected]",
  "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": "[email protected]"
}

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": "[email protected]"
  }
}
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

With Pagination

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:
  1. Filters published posts in Technology category
  2. Returns only id, title, and excerpt from posts
  3. Joins author with name and avatar
  4. Sorts by publish date (newest first)
  5. Returns 20 posts per page
  6. Returns first page

Performance Benefits

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

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

  1. Always select only needed fields: Don’t default to selecting all fields
  2. Configure field access: Use exclude or allow in your controller
  3. Protect sensitive data: Never expose passwords, tokens, or internal fields
  4. Use TypeScript: Define interfaces for different field selections
  5. Document available fields: Clearly document which fields are available
  6. Consider mobile clients: Select minimal fields for mobile endpoints
  7. Test performance: Measure the impact of field selection on performance
  8. 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

Build docs developers (and LLMs) love