๐Ÿ“ฆ payloadcms / payload

๐Ÿ“„ overview.mdx ยท 322 lines
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322---
title: Querying your Documents
label: Overview
order: 10
desc: Payload provides a querying language through all APIs, allowing you to filter or search through documents within a Collection.
keywords: query, documents, overview, documentation, Content Management System, cms, headless, javascript, node, react, nextjs
---

In Payload, "querying" means filtering or searching through Documents within a [Collection](../configuration/collections). The querying language in Payload is designed to be simple and powerful, allowing you to filter Documents with extreme precision through an intuitive and standardized structure.

Payload provides three common APIs for querying your data:

- [Local API](/docs/local-api/overview) - Extremely fast, direct-to-database access
- [REST API](/docs/rest-api/overview) - Standard HTTP endpoints for querying and mutating data
- [GraphQL](/docs/graphql/overview) - A full GraphQL API with a GraphQL Playground

Each of these APIs share the same underlying querying language, and fully support all of the same features. This means that you can learn Payload's querying language once, and use it across any of the APIs that you might use.

To query your Documents, you can send any number of [Operators](#operators) through your request:

```ts
import type { Where } from 'payload'

const query: Where = {
  color: {
    equals: 'blue',
  },
}
```

_The exact query syntax will depend on the API you are using, but the concepts are the same across all APIs. [More details](#writing-queries)._

<Banner>
  **Tip:** You can also use queries within [Access
  Control](../access-control/overview) functions.
</Banner>

## Operators

The following operators are available for use in queries:

| Operator             | Description                                                                                                                                                                      |
| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `equals`             | The value must be exactly equal.                                                                                                                                                 |
| `not_equals`         | The query will return all documents where the value is not equal.                                                                                                                |
| `greater_than`       | For numeric or date-based fields.                                                                                                                                                |
| `greater_than_equal` | For numeric or date-based fields.                                                                                                                                                |
| `less_than`          | For numeric or date-based fields.                                                                                                                                                |
| `less_than_equal`    | For numeric or date-based fields.                                                                                                                                                |
| `like`               | Case-insensitive string must be present. If string of words, all words must be present, in any order.                                                                            |
| `contains`           | Must contain the value entered, case-insensitive.                                                                                                                                |
| `in`                 | The value must be found within the provided comma-delimited list of values.                                                                                                      |
| `not_in`             | The value must NOT be within the provided comma-delimited list of values.                                                                                                        |
| `all`                | The value must contain all values provided in the comma-delimited list. Note: currently this operator is supported only with the MongoDB adapter.                                |
| `exists`             | Only return documents where the value either exists (`true`) or does not exist (`false`).                                                                                        |
| `near`               | For distance related to a [Point Field](../fields/point) comma separated as `<longitude>, <latitude>, <maxDistance in meters (nullable)>, <minDistance in meters (nullable)>`.   |
| `within`             | For [Point Fields](../fields/point) to filter documents based on whether points are inside of the given area defined in GeoJSON. [Example](../fields/point#querying-within)      |
| `intersects`         | For [Point Fields](../fields/point) to filter documents based on whether points intersect with the given area defined in GeoJSON. [Example](../fields/point#querying-intersects) |

<Banner type="success">
  **Tip:** If you know your users will be querying on certain fields a lot, add
  `index: true` to the Field Config. This will speed up searches using that
  field immensely. [More details](../database/indexes).
</Banner>

### And / Or Logic

In addition to defining simple queries, you can join multiple queries together using AND / OR logic. These can be nested as deeply as you need to create complex queries.

To join queries, use the `and` or `or` keys in your query object:

```ts
import type { Where } from 'payload'

const query: Where = {
  or: [
    // highlight-line
    {
      color: {
        equals: 'mint',
      },
    },
    {
      and: [
        // highlight-line
        {
          color: {
            equals: 'white',
          },
        },
        {
          featured: {
            equals: false,
          },
        },
      ],
    },
  ],
}
```

Written in plain English, if the above query were passed to a `find` operation, it would translate to finding posts where either the `color` is `mint` OR the `color` is `white` AND `featured` is set to false.

### Nested properties

When working with nested properties, which can happen when using relational fields, it is possible to use the dot notation to access the nested property. For example, when working with a `Song` collection that has an `artists` field which is related to an `Artists` collection using the `name: 'artists'`. You can access a property within the collection `Artists` like so:

```js
import type { Where } from 'payload'

const query: Where = {
  'artists.featured': {
    // nested property name to filter on
    exists: true, // operator to use and boolean value that needs to be true
  },
}
```

## Writing Queries

Writing queries in Payload is simple and consistent across all APIs, with only minor differences in syntax between them.

### Local API

The [Local API](../local-api/overview) supports the `find` operation that accepts a raw query object:

```ts
import type { Payload } from 'payload'

const getPosts = async (payload: Payload) => {
  const posts = await payload.find({
    collection: 'posts',
    where: {
      color: {
        equals: 'mint',
      },
    },
  })

  return posts
}
```

### GraphQL API

All `find` queries in the [GraphQL API](../graphql/overview) support the `where` argument that accepts a raw query object:

```ts
query {
  Posts(where: { color: { equals: mint } }) {
    docs {
      color
    }
    totalDocs
  }
}
```

### REST API

With the [REST API](../rest-api/overview), you can use the full power of Payload queries, but they are written as query strings instead:

**`https://localhost:3000/api/posts?where[color][equals]=mint`**

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-esm`](https://www.npmjs.com/package/qs-esm) package to parse your JSON / object-formatted queries into query strings:

```ts
import { stringify } from 'qs-esm'
import type { Where } from 'payload'

const query: Where = {
  color: {
    equals: 'mint',
  },
  // This query could be much more complex
  // and qs-esm would handle it beautifully
}

const getPosts = async () => {
  const stringifiedQuery = stringify(
    {
      where: query, // ensure that `qs-esm` adds the `where` property, too!
    },
    { addQueryPrefix: true },
  )

  const response = await fetch(
    `http://localhost:3000/api/posts${stringifiedQuery}`,
  )
  // Continue to handle the response below...
}
```

## Performance

There are several ways to optimize your queries. Many of these options directly impact overall database overhead, response sizes, and/or computational load and can significantly improve performance.

When building queries, combine as many of these strategies together as possible to ensure your queries are as performant as they can be.

<Banner type="success">
  For more performance tips, see the [Performance
  documentation](../performance/overview).
</Banner>

### Indexes

Build [Indexes](../database/indexes) for fields that are often queried or sorted by.

When your query runs, the database will not search the entire document to find that one field, but will instead use the index to quickly locate the data.

This is done by adding `index: true` to the Field Config for that field:

```ts
// In your collection configuration
{
  name: 'posts',
  fields: [
    {
      name: 'title',
      type: 'text',
      // highlight-start
      index: true, // Add an index to the title field
      // highlight-end
    },
    // Other fields...
  ],
}
```

To learn more, see the [Indexes documentation](../database/indexes).

### Depth

Set the [Depth](./depth) to only the level that you need to avoid populating unnecessary related documents.

Relationships will only populate down to the specified depth, and any relationships beyond that depth will only return the ID of the related document.

```ts
const posts = await payload.find({
  collection: 'posts',
  where: { ... },
  // highlight-start
  depth: 0, // Only return the IDs of related documents
  // highlight-end
})
```

To learn more, see the [Depth documentation](./depth).

### Limit

Set the [Limit](./pagination#limit) if you can reliably predict the number of matched documents, such as when querying on a unique field.

```ts
const posts = await payload.find({
  collection: 'posts',
  where: {
    slug: {
      equals: 'unique-post-slug',
    },
  },
  // highlight-start
  limit: 1, // Only expect one document to be returned
  // highlight-end
})
```

<Banner type="success">
  **Tip:** Use in combination with `pagination: false` for best performance when
  querying by unique fields.
</Banner>

To learn more, see the [Limit documentation](./pagination#limit).

### Select

Use the [Select API](./select) to only process and return the fields you need.

This will reduce the amount of data returned from the request, and also skip processing of any fields that are not selected, such as running their field hooks.

```ts
const posts = await payload.find({
  collection: 'posts',
  where: { ... },
  // highlight-start
  select: [{
    title: true,
  }],
  // highlight-end
```

This is a basic example, but there are many ways to use the Select API, including selecting specific fields, excluding fields, etc.

To learn more, see the [Select documentation](./select).

### Pagination

[Disable Pagination](./pagination#disabling-pagination) if you can reliably predict the number of matched documents, such as when querying on a unique field.

```ts
const posts = await payload.find({
  collection: 'posts',
  where: {
    slug: {
      equals: 'unique-post-slug',
    },
  },
  // highlight-start
  pagination: false, // Return all matched documents without pagination
  // highlight-end
})
```

<Banner type="success">
  **Tip:** Use in combination with `limit: 1` for best performance when querying
  by unique fields.
</Banner>

To learn more, see the [Pagination documentation](./pagination).