文档服务 API:publicationFilter

页面摘要: 使用可选的 publicationFilter 参数,根据文档草稿版本与已发布版本之间的关系查询文档,例如从未发布的草稿,或自上次发布以来已修改的条目。它可与 findOne()、findFirst()、findMany() 和 count() 配合使用,并可与其它查询参数组合。status 仍然决定你获取的是草稿还是已发布版本。

publicationFilter 是一个参数,与 the status 参数 结合使用,可帮助你使用 文档服务 API 覆盖复杂的查询,精确找到所需内容。

status 回答的是「我要草稿还是已发布版本?」,而 publicationFilter 参数回答的是另一个问题:「基于草稿版本与已发布版本之间的关系,我想要哪些文档?」。例如,这可用于查找从未发布的草稿,或者草稿相比线上版本有未保存更改的条目。

WARNING

必须在内容类型上启用 草稿与发布 功能。如果禁用了草稿与发布,publicationFilter 不会生效。

可用值 {#values}

publicationFilter 接受以下值之一:

ValueSelects
never-published在给定本地化下从未发布的文档
never-published-document在任何本地化下都从未发布的文档
modified自上次发布以来草稿被编辑过的文档
unmodified自上次发布以来草稿未变更的文档
has-published-version同时拥有草稿和已发布版本的文档
published-without-draft没有对应草稿的已发布文档
(仅用于诊断)
published-with-draft同时拥有草稿的已发布文档
(仅用于诊断)
has-published-version-document在至少一个本地化下已发布的文档
(启用 i18n 时有用)

有关如何使用 publicationFilter 各值的详细示例(包括与 status 参数的搭配),请参阅 可能的用例 表格。

NOTE
  • 未知的值会引发校验错误。
  • 以 -document 结尾的值会考虑文档的所有本地化,这在启用 国际化(i18n) 时很重要:例如,只要文档的某个本地化被发布了,never-published-document 就会将其排除。所有其他值一次只考虑一个本地化。在未启用 i18n 时,两种变体行为相同。
注意:不同 API 的默认行为不同

文档服务 API 在省略 status 时返回文档的草稿版本,而 REST 和 GraphQL 返回的是已发布版本,因此 REST API 查询需要显式指定 status(请参阅 REST API:publicationFilter)。

可能的用例 {#use-cases}

下表列出了许多可能的用例,展示了如何将 status 和 publicationFilter 参数组合使用,以通过文档服务 API 精确找到所需内容。点击用例可跳转到完整示例:

I want to…Use status as…Use publicationFilter as…
查找从未发布的草稿draftnever-published
查找任何本地化下都从未发布的草稿draftnever-published-document
查找已修改的文档draft 或 publishedmodified
查找未修改的文档draft 或 publishedunmodified
查找拥有已发布版本的文档draft 或 publishedhas-published-version
查找在至少一个本地化下已发布的文档draft 或 publishedhas-published-version-document
与 findOne() 和 findFirst() 搭配使用draft 或 published任意值
仅统计匹配的文档draft 或 published任意值
NOTE

将某个值与表中相反的 status 搭配是合法的,但返回空结果而非错误:例如,never-published 配合 status: 'published' 会返回空结果,因为这些文档尚无已发布版本。

示例

以下小节列出了 上表 中归纳的最常见用例。

查找从未发布的草稿 {#never-published}

最常见的用例之一是查找从未发布的草稿。为此,传入 status: 'draft' 和 publicationFilter: 'never-published'。

此参数组合仅作用于给定本地化;要跨所有本地化查找这些文档,请改用 use never-published-document。

返回其本地化下从未被发布的草稿。

JavaScript

await strapi.documents('api::restaurant.restaurant').findMany({
    status: 'draft',
    publicationFilter: 'never-published',
});

响应

[
    {
      documentId: "a1b2c3d4e5f6g7h8i9j0klm",
      name: "New Restaurant",
      publishedAt: null,
      locale: "en", // 默认本地化
      // …
    }
  // …
]

查找任何本地化下都从未发布的草稿 {#never-published-document}

publicationFilter: never-published-document 返回在任何本地化下都从未发布的文档。它关注的是文档跨所有本地化的整体,而非一次只看一个本地化。若只需针对给定本地化查找这些文档,请改用 use never-published。

只要文档的某个本地化被发布,该文档即被视为已发布:此时该文档会被排除,即使是仅以草稿形式存在的本地化也不例外。以下示例返回在任何本地化下都从未发布的文档的草稿版本:

返回在任何本地化下都从未发布的文档的草稿。

JavaScript

await strapi.documents('api::restaurant.restaurant').findMany({
    status: 'draft',
    publicationFilter: 'never-published-document',
});

响应

[
    {
      documentId: "d41r46wac4xix5vpba7561at",
      name: "New Restaurant",
      publishedAt: null,
      locale: "en", // 默认本地化
      // …
    }
  // …
]

查找已修改的文档 {#modified}

publicationFilter: modified 选择草稿中存在已修改但未发布的更改的文档。status 随后决定你获取的是这些文档的哪个版本。

例如,使用 status: 'draft' 时,查询返回草稿版本:

返回存在未发布更改的文档的草稿版本。

JavaScript

await strapi.documents('api::restaurant.restaurant').findMany({
    status: 'draft',
    publicationFilter: 'modified',
});

响应

[
    {
      documentId: "a1b2c3d4e5f6g7h8i9j0klm",
      name: "Biscotte Restaurant (updated)",
      publishedAt: null,
      locale: "en", // 默认本地化
      // …
    }
  // …
]

使用 status: 'published' 时,同样的查询会返回这些文档当前线上的版本:

返回存在未发布更改的文档当前线上的版本。

JavaScript

await strapi.documents('api::restaurant.restaurant').findMany({
    status: 'published',
    publicationFilter: 'modified',
});

响应

[
    {
      documentId: "a1b2c3d4e5f6g7h8i9j0klm",
      name: "Biscotte Restaurant",
      publishedAt: "2024-03-14T15:40:45.330Z",
      locale: "en", // 默认本地化
      // …
    }
  // …
]

查找未修改的文档 {#unmodified}

publicationFilter: unmodified 选择自上次发布以来草稿未变更的文档。status 随后决定你获取的是这些文档的哪个版本。

例如,使用 status: 'draft' 时,查询返回草稿版本:

返回自上次发布以来未变更的文档的草稿版本。

JavaScript

await strapi.documents('api::restaurant.restaurant').findMany({
    status: 'draft',
    publicationFilter: 'unmodified',
});

响应

[
    {
      documentId: "a1b2c3d4e5f6g7h8i9j0klm",
      name: "Biscotte Restaurant",
      publishedAt: null,
      locale: "en", // 默认本地化
      // …
    }
  // …
]

使用 status: 'published' 时,同样的查询会返回这些文档当前线上的版本:

返回自上次发布以来未变更的文档当前线上的版本。

JavaScript

await strapi.documents('api::restaurant.restaurant').findMany({
    status: 'published',
    publicationFilter: 'unmodified',
});

响应

[
    {
      documentId: "a1b2c3d4e5f6g7h8i9j0klm",
      name: "Biscotte Restaurant",
      publishedAt: "2024-03-14T15:40:45.330Z",
      locale: "en", // 默认本地化
      // …
    }
  // …
]

查找拥有已发布版本的文档 {#has-published-version}

publicationFilter: has-published-version 选择同一本地化下同时拥有草稿和已发布版本的文档。status 随后决定你获取的是这些文档的哪个版本。

例如,使用 status: 'draft' 时,查询返回草稿版本:

返回同一本地化下也拥有已发布版本的文档的草稿版本。

JavaScript

await strapi.documents('api::restaurant.restaurant').findMany({
    status: 'draft',
    publicationFilter: 'has-published-version',
});

响应

[
    {
      documentId: "a1b2c3d4e5f6g7h8i9j0klm",
      name: "Biscotte Restaurant",
      publishedAt: null,
      locale: "en", // 默认本地化
      // …
    }
  // …
]

使用 status: 'published' 时,同样的查询会返回这些文档当前线上的版本:

返回同一本地化下也拥有已发布版本的文档当前线上的版本。

JavaScript

await strapi.documents('api::restaurant.restaurant').findMany({
    status: 'published',
    publicationFilter: 'has-published-version',
});

响应

[
    {
      documentId: "a1b2c3d4e5f6g7h8i9j0klm",
      name: "Biscotte Restaurant",
      publishedAt: "2024-03-14T15:40:45.330Z",
      locale: "en", // 默认本地化
      // …
    }
  // …
]

查找在至少一个本地化下已发布的文档 {#has-published-version-document}

publicationFilter: has-published-version-document 考虑所有本地化,因此只要文档的某个本地化被发布即匹配。使用 status: 'draft' 时,它会返回这些文档每个本地化的草稿版本,包括那些本身从未被发布的本地化:

返回在至少一个本地化下已发布的文档的草稿版本。

JavaScript

await strapi.documents('api::restaurant.restaurant').findMany({
    status: 'draft',
    publicationFilter: 'has-published-version-document',
});

响应

[
    {
      documentId: "a1b2c3d4e5f6g7h8i9j0klm",
      name: "Biscotte Restaurant",
      publishedAt: null,
      locale: "en", // 在至少一个本地化下已发布
      // …
    }
  // …
]

与 findOne() 和 findFirst() 搭配使用 {#find-one-find-first}

如果所请求的文档(以及适用的本地化)不匹配过滤器,findOne() 和 findFirst() 即使 documentId 存在也会返回 null:

仅当文档匹配过滤器时返回该文档,否则返回 null。

JavaScript

await strapi.documents('api::restaurant.restaurant').findOne({
    documentId: 'a1b2c3d4e5f6g7h8i9j0klm',
    status: 'draft',
    publicationFilter: 'never-published',
});

响应

null // documentId 存在,但文档不匹配 never-published

仅统计匹配的文档 {#count}

如果不使用 publicationFilter,count({ status: 'draft' }) 会统计每一个草稿版本,包括其文档已拥有已发布版本的草稿。添加 publicationFilter 可仅统计匹配给定值的文档(参见 status 文档):

仅统计匹配给定值的文档。

JavaScript

const neverPublishedCount = await strapi
    .documents('api::restaurant.restaurant')
    .count({
      status: 'draft',
      publicationFilter: 'never-published',
    });

响应

12 // 从未发布的草稿数量

诊断值 {#diagnostics}

published-without-draft 和 published-with-draft 这两个值仅用于数据完整性检查,而非日常查询。在健康的数据库中,每个已发布文档也都拥有一个草稿版本,因此这些值仅有助于检测因遗留数据或手动数据库编辑而处于不一致状态的文档。它们仅可与 status: 'published' 配合使用。

显示诊断值示例

publicationFilter: published-without-draft 选择没有对应草稿的已发布文档。在正常运行情况下,这应返回空结果:

返回同一本地化下没有匹配草稿版本的已发布文档。

JavaScript

await strapi.documents('api::restaurant.restaurant').findMany({
    status: 'published',
    publicationFilter: 'published-without-draft',
});

响应

[
  {
    documentId: "j0klm1n2o3p4q5r6s7t8u9v",
    name: "Legacy Restaurant",
    publishedAt: "2024-01-10T09:15:00.000Z",
    locale: "en", // 默认本地化
    // …
  }
  // …
]

publicationFilter: published-with-draft 选择同时拥有草稿的已发布文档,在健康的数据库中即每一个已发布文档:

返回同一本地化下也拥有匹配草稿版本的已发布文档。

JavaScript

await strapi.documents('api::restaurant.restaurant').findMany({
    status: 'published',
    publicationFilter: 'published-with-draft',
});

响应

[
    {
      documentId: "a1b2c3d4e5f6g7h8i9j0klm",
      name: "Biscotte Restaurant",
      publishedAt: "2024-03-14T15:40:45.330Z",
      locale: "en", // 默认本地化
      // …
    }
  // …
]

与其它参数的组合 {#combine}

publicationFilter 作为逻辑 AND 与其它查询参数组合使用,包括 filters 和 populate。在联表加载草稿与发布关系时,嵌套查询会继承相同的过滤逻辑。

内容管理器映射 {#content-manager}

在内容管理器中,**草稿(从未发布)**列表过滤器映射到 status: 'draft' 和 publicationFilter: 'never-published-document'(文档级范围,而非按本地化的 never-published)。