### What?
Adds `populate` property to Local API and REST API operations that can
be used to specify `select` for a specific collection when it's
populated
```ts
const result = await payload.findByID({
populate: {
// type safe if you have generated types
posts: {
text: true,
},
},
collection: 'pages',
depth: 1,
id: aboutPage.id,
})
result.relatedPost // only has text and id properties
```
```ts
fetch('https://localhost:3000/api/pages?populate[posts][text]=true') // highlight-line
.then((res) => res.json())
.then((data) => console.log(data))
```
It also overrides
[`defaultPopulate`](https://github.com/payloadcms/payload/pull/8934)
Ensures `defaultPopulate` doesn't affect GraphQL.
### How?
Implements the property for all operations that have the `depth`
argument.
159 lines
4.1 KiB
Plaintext
159 lines
4.1 KiB
Plaintext
---
|
|
title: Select
|
|
label: Select
|
|
order: 30
|
|
desc: Payload select determines which fields are selected to the result.
|
|
keywords: query, documents, pagination, documentation, Content Management System, cms, headless, javascript, node, react, nextjs
|
|
---
|
|
|
|
You may not need the full data from your Local API / REST queries, but only some specific fields. The select fields API can help you to optimize those cases.
|
|
|
|
## Local API
|
|
|
|
To specify select in the [Local API](../local-api/overview), you can use the `select` option in your query:
|
|
|
|
```ts
|
|
// Include mode
|
|
const getPosts = async () => {
|
|
const posts = await payload.find({
|
|
collection: 'posts',
|
|
select: {
|
|
text: true,
|
|
// select a specific field from group
|
|
group: {
|
|
number: true
|
|
},
|
|
// select all fields from array
|
|
array: true,
|
|
}, // highlight-line
|
|
})
|
|
|
|
return posts
|
|
}
|
|
|
|
// Exclude mode
|
|
const getPosts = async () => {
|
|
const posts = await payload.find({
|
|
collection: 'posts',
|
|
// Select everything except for array and group.number
|
|
select: {
|
|
array: false,
|
|
group: {
|
|
number: false
|
|
}
|
|
}, // highlight-line
|
|
})
|
|
|
|
return posts
|
|
}
|
|
```
|
|
|
|
|
|
<Banner type="warning">
|
|
<strong>Important:</strong>
|
|
To perform querying with `select` efficiently, it works on the database level. Because of that, your `beforeRead` and `afterRead` hooks may not receive the full `doc`.
|
|
</Banner>
|
|
|
|
|
|
## REST API
|
|
|
|
To specify select in the [REST API](../rest-api/overview), you can use the `select` parameter in your query:
|
|
|
|
```ts
|
|
fetch('https://localhost:3000/api/posts?select[color]=true&select[group][number]=true') // highlight-line
|
|
.then((res) => res.json())
|
|
.then((data) => console.log(data))
|
|
```
|
|
|
|
To understand the syntax, you need to understand that complex URL search strings are parsed into a JSON object. This one isn't too bad, but more complex queries get unavoidably more difficult to write.
|
|
|
|
For this reason, we recommend to use the extremely helpful and ubiquitous [`qs`](https://www.npmjs.com/package/qs) package to parse your JSON / object-formatted queries into query strings:
|
|
|
|
```ts
|
|
import { stringify } from 'qs-esm'
|
|
|
|
const select = {
|
|
text: true,
|
|
group: {
|
|
number: true
|
|
}
|
|
// This query could be much more complex
|
|
// and QS would handle it beautifully
|
|
}
|
|
|
|
const getPosts = async () => {
|
|
const stringifiedQuery = stringify(
|
|
{
|
|
select, // ensure that `qs` adds the `select` property, too!
|
|
},
|
|
{ addQueryPrefix: true },
|
|
)
|
|
|
|
const response = await fetch(`http://localhost:3000/api/posts${stringifiedQuery}`)
|
|
// Continue to handle the response below...
|
|
}
|
|
```
|
|
|
|
<Banner type="info">
|
|
<strong>Reminder:</strong>
|
|
This is the same for [Globals](../configuration/globals) using the `/api/globals` endpoint.
|
|
</Banner>
|
|
|
|
|
|
## `defaultPopulate` collection config property
|
|
|
|
The `defaultPopulate` property allows you specify which fields to select when populating the collection from another document.
|
|
This is especially useful for links where only the `slug` is needed instead of the entire document.
|
|
|
|
```ts
|
|
import type { CollectionConfig } from 'payload'
|
|
|
|
import { lexicalEditor, LinkFeature } from '@payloadcms/richtext-lexical'
|
|
import { slateEditor } from '@payloadcms/richtext-slate'
|
|
|
|
// The TSlug generic can be passed to have type safety for `defaultPopulate`.
|
|
// If avoided, the `defaultPopulate` type resolves to `SelectType`.
|
|
export const Pages: CollectionConfig<'pages'> = {
|
|
slug: 'pages',
|
|
// Specify `select`.
|
|
defaultPopulate: {
|
|
slug: true,
|
|
},
|
|
fields: [
|
|
{
|
|
name: 'slug',
|
|
type: 'text',
|
|
required: true,
|
|
},
|
|
],
|
|
}
|
|
```
|
|
|
|
## `populate`
|
|
|
|
You can override `defaultPopulate` with the `populate` property in the Local and REST API
|
|
|
|
Local API:
|
|
```ts
|
|
const getPosts = async () => {
|
|
const posts = await payload.find({
|
|
collection: 'posts',
|
|
populate: {
|
|
// Select only `text` from populated docs in the "pages" collection
|
|
pages: {
|
|
text: true,
|
|
}, // highlight-line
|
|
},
|
|
})
|
|
|
|
return posts
|
|
}
|
|
```
|
|
|
|
REST API:
|
|
```ts
|
|
fetch('https://localhost:3000/api/posts?populate[pages][text]=true') // highlight-line
|
|
.then((res) => res.json())
|
|
.then((data) => console.log(data))
|
|
```
|