文档服务 API:联表加载字段

页面摘要: 在文档服务 API 中使用 populate 参数,可以在一层或多层深度显式加载关系、媒体字段、组件和动态区域,并可在 create()、update()、publish() 和 delete() 操作中使用。

默认情况下,文档服务 API 不会联表加载任何关系、媒体字段、组件或动态区域。本页介绍如何使用 populate 参数来联表加载特定字段。

TIP

你也可以使用 fields 参数让查询结果仅返回特定字段(参见 fields 参数 文档)。

WARNING

如果启用了用户与权限功能,必须为被联表加载的内容类型启用 find 权限。如果某个角色无权访问某个内容类型,该内容类型将不会被联表加载。

关系与媒体字段

查询可以接受 populate 参数,以显式定义要联表加载哪些字段,语法选项示例如下。这包括所有关系类型:一对多、多对一、多对多,以及多态关系(morphToOne、morphToMany)。

联表加载所有关系的一层

使用通配符为所有关系联表加载一层深度。

JavaScript

const documents = await strapi.documents("api::article.article").findMany({
  populate: "*",
});

响应

{
  [
    {
      "id": "cjld2cjxh0000qzrmn831i7rn",
      "title": "Test Article",
      "slug": "test-article",
      "body": "Test 1",
      // ...
      "headerImage": {
        "data": {
          "id": 1,
          "attributes": {
            "name": "17520.jpg",
            "alternativeText": "17520.jpg",
            "formats": {
              // ...
            }
            // ...
          }
        }
      },
      "author": {
        // ...
      },
      "categories": {
        // ...
      }
    }
    // ...
  ]
}

联表加载特定关系的一层

使用数组为特定关系联表加载一层深度。

JavaScript

const documents = await strapi.documents("api::article.article").findMany({
  populate: ["headerImage"],
});

响应

[
  {
    "id": "cjld2cjxh0000qzrmn831i7rn",
    "title": "Test Article",
    "slug": "test-article",
    "body": "Test 1",
    // ...
    "headerImage": {
      "id": 2,
      "name": "17520.jpg"
      // ...
    }
  }
  // ...
]

联表加载特定关系的多层深度

使用嵌套 populate 为特定关系联表加载多层深度。

JavaScript

const documents = await strapi.documents("api::article.article").findMany({
  populate: {
    categories: {
      populate: ["articles"],
    },
  },
});

响应

[
  {
    "id": "cjld2cjxh0000qzrmn831i7rn",
    "title": "Test Article",
    "slug": "test-article",
    "body": "Test 1",
    // ...
    "categories": {
      "id": 1,
      "name": "Test Category",
      "slug": "test-category",
      "description": "Test 1"
      // ...
      "articles": [
        {
          "id": 1,
          "title": "Test Article",
          "slug": "test-article",
          "body": "Test 1",
          // ...
        }
        // ...
      ]
    }
  }
  // ...
]

对联表加载的关系排序

在 populate 对象内部使用 sort 参数,可按某个属性对关联条目进行排序。对于多对多及其他连接表关系,显式的 sort 会优先于默认的关联顺序。

在 populate 对象内部使用 sort 参数,按属性对关联条目排序。

JavaScript

const documents = await strapi.documents("api::article.article").findMany({
  populate: {
    categories: {
      sort: 'name:asc',
    },
  },
});

响应

[
  {
    "id": "cjld2cjxh0000qzrmn831i7rn",
    "title": "Test Article",
    // ...
    "categories": [
      {
        "id": 1,
        "name": "Architecture"
        // ...
      },
      {
        "id": 3,
        "name": "Technology"
        // ...
      }
    ]
  }
  // ...
]
NOTE

在 populate 对象中省略 sort 可保留默认的关联顺序(即条目被关联时的顺序)。

组件与动态区域

NOTE

被联表加载时,空的 morphMany 关系(包括 type: 'media', multiple: true 等字段,例如图库)会返回 [] 而非 null,这与 oneToMany 和 manyToMany 一致。迁移指导请参阅 morphMany 序列化破坏性变更。

组件的联表加载方式与关系相同:

使用与关系相同的语法联表加载组件。

JavaScript

const documents = await strapi.documents("api::article.article").findMany({
  populate: ["testComp"],
});

响应

[
  {
    "id": "cjld2cjxh0000qzrmn831i7rn",
    "title": "Test Article",
    "slug": "test-article",
    "body": "Test 1",
    // ...
    "testComp": {
      "id": 1,
      "name": "Test Component"
      // ...
    }
  }
  // ...
]

动态区域本质上高度动态的内容结构。标准的联表加载查询(如 populate: '*' 或 populate: ['testDZ'])只会检索动态区域内组件的默认、非关系型标量字段(例如字符串、数字)。它们不会自动获取嵌套关系、媒体字段或嵌套组件。

要联表加载动态区域内组件特定的嵌套关系、媒体字段或组件,必须使用 on 属性(片段联表加载语法)定义针对每个组件的联表加载查询。

使用 on 属性通过针对组件的查询来联表加载动态区域。

JavaScript

const documents = await strapi.documents("api::article.article").findMany({
  populate: {
    testDZ: {
      on: {
        "test.test-compo": {
          fields: ["testString"],
          populate: ["testNestedCompo"],
        },
      },
    },
  },
});

响应

[
  {
    "id": "cjld2cjxh0000qzrmn831i7rn",
    "title": "Test Article",
    "slug": "test-article",
    "body": "Test 1",
    // ...
    "testDZ": [
      {
        "id": 3,
        "__component": "test.test-compo",
        "testString": "test1",
        "testNestedCompo": {
          "id": 3,
          "testNestedString": "testNested1"
        }
      }
    ]
  }
  // ...
]

在 create() 中联表加载

在创建文档时于响应中联表加载关系。

JavaScript

strapi.documents("api::article.article").create({
  data: {
    title: "Test Article",
    slug: "test-article",
    body: "Test 1",
    headerImage: 2,
  },
  populate: ["headerImage"],
});

响应

{
  "id": "cjld2cjxh0000qzrmn831i7rn",
  "title": "Test Article",
  "slug": "test-article",
  "body": "Test 1",
  "headerImage": {
    "id": 2,
    "name": "17520.jpg"
    // ...
  }
}

在 update() 中联表加载

在更新文档时于响应中联表加载关系。

JavaScript

strapi.documents("api::article.article").update({
  documentId: "cjld2cjxh0000qzrmn831i7rn",
  data: {
    title: "Test Article Update",
  },
  populate: ["headerImage"],
});

响应

{
  "id": "cjld2cjxh0000qzrmn831i7rn",
  "title": "Test Article Update",
  "slug": "test-article",
  "body": "Test 1",
  "headerImage": {
    "id": 2,
    "name": "17520.jpg"
    // ...
  }
}

在 publish() 中联表加载

unpublish() 和 discardDraft() 适用相同的行为。

在发布文档时于响应中联表加载关系。

JavaScript

strapi.documents("api::article.article").publish({
  documentId: "cjld2cjxh0000qzrmn831i7rn",
  populate: ["headerImage"],
});

响应

{
  "id": "cjld2cjxh0000qzrmn831i7rn",
  "versions": [
    {
      "id": "cjld2cjxh0001qzrm1q1i7rn",
      "locale": "en",
      // ...
      "headerImage": {
        "id": 2,
        "name": "17520.jpg"
        // ...
      }
    }
  ]
}

在 delete() 中联表加载

要在删除文档时联表加载:

在删除文档时于响应中联表加载关系。

JavaScript

strapi.documents("api::article.article").delete({
  documentId: "cjld2cjxh0000qzrmn831i7rn",
  populate: ["headerImage"],
});

响应

{
  "documentId": "cjld2cjxh0000qzrmn831i7rn",
  "entries": [
    {
      "id": "cjld2cjxh0000qzrmn831i7rn",
      "title": "Test Article",
      "slug": "test-article",
      "body": "Test 1",
      "headerImage": {
        "id": 2,
        "name": "17520.jpg"
        // ...
      }
      // ...
    }
  ]
}