Skip to main content

Field projection

Reduce bandwidth and improve performance by returning only the fields you need from queries.

When querying documents with many fields, you often only need a subset of that data. Without field projection, your application fetches entire documents even when displaying just a name and email in a list view. Field projection reduces bandwidth and improves performance by letting you specify exactly which fields to return. Projection happens on the server, so you're reducing network transfer rather than filtering data client-side.

Client code
// Without projection: fetches all 20+ fields
const users = await squid.collection<User>('users').query().snapshot();

// With projection: fetches only what you need
const users = await squid.collection<User>('users').query().projectFields(['name', 'email']).snapshot();

Quick start

Call projectFields on any query with an array of field names:

Client code
const results = await squid.collection<User>('users').query().projectFields(['name', 'age']).dereference().snapshot();

// Results contain only the projected fields

Field projection works with all query methods:

Client code
const results = await squid.collection<User>('users').query().where('status', '==', 'active').sortBy('name').limit(50).projectFields(['name', 'email', 'status']).dereference().snapshot();

Core concepts

Document identifiers are always included

Regardless of which fields you project, the following identifiers are always included in results:

  • __docId__: The document's unique identifier, present on all database integrations. You can use it for filtering and sorting even without including it in your projection.
  • __id: The document's primary key value, present only when using the built-in database.
Client code
// Filter by __docId__ without projecting it
const results = await squid.collection<User>('users').query().where('__docId__', '>=', 'user_100').projectFields(['name', 'email']).dereference().snapshot();

For collections with composite primary keys, the individual key fields are also included at the top level of results.

Nested fields

Use dot notation to project nested field paths:

Client code
interface User {
name: string;
address: {
city: string;
zip: string;
country: string;
};
}

const results = await squid.collection<User>('users').query().projectFields(['name', 'address.city']).dereference().snapshot();

// Result: { name: 'Alice', address: { city: 'NYC' } }
// Note: address.zip and address.country are NOT included

Validation rules

Note

Document identifier fields (__docId__ and __id) are exceptions to these rules - they can always be used for filtering and sorting without being included in your projection.

Filter fields must be in projection

When using projectFields, any field used in a where clause must be included in the projection:

Client code
const usersCollection = squid.collection<User>('users');

// Error: Cannot filter by 'email' that is not included in projectFields
usersCollection.query().where('email', '==', 'test@example.com').projectFields(['name', 'age']);

// Correct: Include email in projection
usersCollection.query().where('email', '==', 'test@example.com').projectFields(['name', 'age', 'email']);

Sort fields must be in projection

Fields used in sortBy must be included in the projection:

Client code
const usersCollection = squid.collection<User>('users');

// Error: Cannot sort by 'email' that is not included in projectFields
usersCollection.query().sortBy('email').projectFields(['name', 'age']);

// Correct: Include email in projection
usersCollection.query().sortBy('email').projectFields(['name', 'age', 'email']);

Empty array behavior

Empty projection arrays behave differently depending on the database:

  • Built-in database: Returns records with only document identifiers, no user data fields.
  • External databases (MongoDB, PostgreSQL, MySQL, etc.): Throws an error. You must specify at least one field.
Client code
// For built-in database: returns records with only identifiers
const results = await squid.collection<User>('users').query().projectFields([]).snapshot();

// For external databases: throws error
const mongoCollection = squid.collection<User>('users', 'mongoConnectorId');
mongoCollection.query().projectFields([]); // Error!

Real-time subscriptions

Field projection works with real-time subscriptions. Each update contains only the projected fields:

Client code
squid
.collection<User>('users')
.query()
.projectFields(['name', 'age'])
.snapshots()
.subscribe((refs) => {
// Each update contains only name and age
console.log(refs.map((ref) => ref.data));
});

Supported databases

Field projection is supported on all Squid database connectors:

  • Built-in database
  • MongoDB
  • PostgreSQL
  • MySQL
  • ClickHouse
  • MS SQL Server