查询文档

在 Payload 中,"querying"(查询)指的是对 Collection 中的文档进行过滤或搜索。Payload 的查询语言设计简洁而强大,通过直观且标准化的结构,让你能够极其精确地筛选文档。

Payload 提供了三种常用的数据查询 API:

  • Local API - 极速直达数据库的访问方式
  • REST API - 标准的 HTTP 端点,用于查询和变更数据
  • GraphQL - 完整的 GraphQL API,附带 GraphQL Playground

这些 API 都共享相同的底层查询语言,并完全支持所有相同的功能。这意味着你只需学习一次 Payload 的查询语言,就可以在所有可能用到的 API 中使用它。

要查询你的文档,你可以通过请求发送任意数量的 操作符

import type { Where } from 'payload'

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

具体的查询语法取决于你使用的 API,但所有 API 的概念都是相同的。更多详情

提示: 你也可以在 访问控制 函数中使用查询。

操作符

以下操作符可用于查询中:

Operator描述
equals值必须完全相等。
not_equals查询将返回所有值不相等的文档。
greater_than适用于数字或日期字段。
greater_than_equal适用于数字或日期字段。
less_than适用于数字或日期字段。
less_than_equal适用于数字或日期字段。
like不区分大小写的字符串必须存在。如果是多个单词组成的字符串,所有单词都必须存在,顺序不限。
contains必须包含输入的值,不区分大小写。
in值必须在提供的逗号分隔的值列表中找到。
not_in值必须不在提供的逗号分隔的值列表中。
all值必须包含逗号分隔列表中提供的所有值。注意:目前此操作符仅支持 MongoDB 适配器。
exists仅返回值存在(true)或不存在的文档(false)。
near用于与 Point Field 相关的距离查询,格式为逗号分隔的 <经度>, <纬度>, <最大距离(米,可选)>, <最小距离(米,可选)>
within用于 Point Fields,根据点是否位于 GeoJSON 定义的给定区域内筛选文档。示例
intersects用于 Point Fields,根据点是否与 GeoJSON 定义的给定区域相交筛选文档。示例

提示: 如果你知道用户会频繁查询某些字段,可以在 Field Config 中添加 index: true。这将极大提高使用该字段的搜索速度。

与/或逻辑

除了定义简单查询外,你还可以使用 AND/OR 逻辑将多个查询组合起来。这些逻辑可以任意深度嵌套,以创建复杂的查询条件。

要组合查询,可以在查询对象中使用 andor 键:

import type { Where } from 'payload'

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

用通俗语言描述,如果上述查询被传递给 find 操作,它将转换为查找满足以下条件的文章:color 等于 mint,或者 color 等于 whitefeatured 设置为 false。

嵌套属性

当处理嵌套属性时(这在关系型字段中很常见),可以使用点符号访问嵌套属性。例如,当处理一个 Song 集合时,该集合有一个 artists 字段,该字段通过 name: 'artists' 关联到 Artists 集合。你可以像这样访问 Artists 集合中的属性:

import type { Where } from 'payload'

const query: Where = {
  'artists.featured': {
    // 要过滤的嵌套属性名
    exists: true, // 使用的操作符及需要为真的布尔值
  },
}

编写查询

在 Payload 中编写查询非常简单,所有 API 的语法都保持一致,只有细微的语法差异。

本地 API

Local API 支持接受原始查询对象的 find 操作:

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

GraphQL API 中,所有 find 查询都支持 where 参数,该参数接受原始查询对象:

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

REST API

通过 REST API,你可以充分利用 Payload 的查询功能,但查询需要以查询字符串的形式编写:

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

要理解这种语法,需要知道复杂的 URL 搜索字符串会被解析为 JSON 对象。这个例子还算简单,但更复杂的查询会不可避免地变得更难编写。

因此,我们推荐使用非常实用且广泛使用的 qs-esm 包,将你的 JSON/对象格式查询解析为查询字符串:

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

const query: Where = {
  color: {
    equals: 'mint',
  },
  // 这个查询可以复杂得多
  // qs-esm 都能完美处理
}

const getPosts = async () => {
  const stringifiedQuery = stringify(
    {
      where: query, // 确保 `qs-esm` 也添加了 `where` 属性!
    },
    { addQueryPrefix: true },
  )

  const response = await fetch(
    `http://localhost:3000/api/posts${stringifiedQuery}`,
  )
  // 继续处理响应...
}