[GRAPHQL] Schema basics (ok)

https://www.apollographql.com/docs/apollo-server/schema/schema/

Máy chủ GraphQL của bạn sử dụng một lược đồ để mô tả hình dạng của biểu đồ dữ liệu của bạn. Lược đồ này xác định hệ thống phân cấp của các loại với các trường được điền từ các kho dữ liệu back-end của bạn. Lược đồ cũng chỉ định chính xác những truy vấn và đột biến nào có sẵn để khách hàng thực thi trên biểu đồ dữ liệu của bạn.

Bài viết này mô tả các khối xây dựng cơ bản của một lược đồ và cách tạo một lược đồ cho máy chủ GraphQL của bạn.

The GraphQL specification includes a human-readable schema definition language (or SDL) that you use to define your schema and store it as a string.

Đặc tả GraphQL bao gồm ngôn ngữ định nghĩa giản đồ có thể đọc được (hoặc SDL) mà bạn sử dụng để xác định lược đồ của mình và lưu trữ nó dưới dạng chuỗi.

Here's a short example schema that defines two object types: Book and Author:

type Book {
  title: String
  author: Author
}

type Author {
  name: String
  books: [Book]
}

Một lược đồ xác định một tập hợp các kiểu và mối quan hệ giữa các kiểu đó. Trong lược đồ ví dụ ở trên, mọi Sách đều có một tác giả và mọi Tác giả đều có một danh sách sách. Bằng cách xác định các mối quan hệ kiểu này trong một lược đồ thống nhất, chúng tôi cho phép các nhà phát triển khách hàng xem chính xác dữ liệu nào có sẵn và yêu cầu một tập hợp con cụ thể của dữ liệu đó với một truy vấn được tối ưu hóa.

Lưu ý rằng lược đồ không chịu trách nhiệm xác định dữ liệu đến từ đâu hoặc cách nó được lưu trữ. Nó hoàn toàn là bất khả tri thực hiện.

Every type definition in a GraphQL schema belongs to one of the following categories:

Kiểu vô hướng tương tự như kiểu nguyên thủy trong ngôn ngữ lập trình yêu thích của bạn. Họ luôn giải quyết dữ liệu cụ thể.

GraphQL's default scalar types are:

Int: Một số nguyên 32 bit có dấu
Float: Giá trị dấu phẩy động có độ chính xác kép đã ký
String: Một chuỗi ký tự UTF ‐ 8
Boolean: đúng hoặc sai
ID (được tuần tự hóa dưới dạng chuỗi): Một số nhận dạng duy nhất thường được sử dụng để tìm nạp lại một đối tượng hoặc làm khóa cho bộ đệm. Mặc dù nó được tuần tự hóa dưới dạng một Chuỗi, một ID không nhằm mục đích con người có thể đọc được.

Các kiểu nguyên thủy này bao gồm phần lớn các trường hợp sử dụng. Đối với các trường hợp sử dụng cụ thể hơn, bạn có thể tạo các loại vô hướng tùy chỉnh.

Hầu hết các kiểu bạn xác định trong lược đồ GraphQL là kiểu đối tượng. Một kiểu đối tượng chứa một tập hợp các trường, mỗi trường có thể là một kiểu vô hướng hoặc một kiểu đối tượng khác.

Hai kiểu đối tượng có thể bao gồm nhau dưới dạng các trường, như trường hợp trong lược đồ ví dụ của chúng tôi trước đó:

type Book {
  title: String
  author: Author
}
type Author {
  name: String
  books: [Book]
}

Loại truy vấn xác định tất cả các điểm nhập cấp cao nhất cho các truy vấn mà khách hàng thực hiện dựa trên biểu đồ dữ liệu của bạn. Nó giống một kiểu đối tượng, nhưng tên của nó luôn là Query.

Mỗi trường của kiểu Truy vấn xác định tên và kiểu trả về của một điểm nhập khác nhau. Loại truy vấn cho lược đồ mẫu của chúng tôi có thể giống như sau:

type Query {
  books: [Book]
  authors: [Author]
}

This Query type defines two fields: books and authors. Each field returns a list of the corresponding type.

Với API dựa trên REST, sách và tác giả có thể sẽ được trả về bởi các điểm cuối khác nhau (ví dụ: / api / books và / api / author). Tính linh hoạt của GraphQL cho phép khách hàng truy vấn cả hai tài nguyên với một yêu cầu duy nhất.

Structuring a query

Khi khách hàng của bạn xây dựng các truy vấn để thực thi dựa trên biểu đồ dữ liệu của bạn, các truy vấn đó khớp với hình dạng của các loại đối tượng mà bạn xác định trong giản đồ của mình

query GetBooksAndAuthors {
  books {
    title
  }
  authors {
    name
  }
}

Our server would then respond to the query with results that match the query's structure, like so:

{
  "data": {
    "books": [
      {
        "title": "City of Glass"
      },
      ...
    ],
    "authors": [
      {
        "name": "Paul Auster"
      },
      ...
    ]
  }
}

Mặc dù có thể hữu ích trong một số trường hợp để tìm nạp hai danh sách riêng biệt này, nhưng khách hàng có thể thích tìm nạp một danh sách sách duy nhất, trong đó tác giả của mỗi cuốn sách được bao gồm trong kết quả.

Vì loại Sách của lược đồ của chúng tôi có trường tác giả thuộc loại Tác giả, thay vào đó, khách hàng có thể cấu trúc truy vấn của họ như vậy:

query GetBooks {
  books {
    title
    author {
      name
    }
  }
}

And once again, our server would respond with results that match the query's structure:

{
  "data": {
    "books": [
      {
        "title": "City of Glass",
        "author": {
          "name": "Paul Auster"
        }
      },
      ...
    ]
  }
}

Kiểu đột biến có cấu trúc và mục đích tương tự như kiểu Truy vấn. Trong khi kiểu Truy vấn xác định điểm vào cho các thao tác đọc, thì kiểu Đột biến xác định điểm vào cho các thao tác ghi.

Mỗi trường của kiểu Mutation xác định kiểu chữ ký và kiểu trả về của một điểm nhập khác nhau. Loại đột biến cho lược đồ ví dụ của chúng tôi có thể giống như sau:

type Mutation {
  addBook(title: String, author: String): Book
}

Loại đột biến này xác định một đột biến có sẵn duy nhất, addBook. Đột biến chấp nhận hai đối số (tiêu đề và tác giả) và trả về đối tượng Sách mới được tạo. Như bạn mong đợi, đối tượng Sách này tuân theo cấu trúc mà chúng tôi đã xác định trong giản đồ của mình.

Structuring a mutation

Giống như truy vấn, các đột biến phù hợp với cấu trúc của các định nghĩa loại lược đồ của bạn. Đột biến sau tạo một Sách mới và yêu cầu các trường nhất định của đối tượng đã tạo làm giá trị trả về:

mutation CreateBook {
  addBook(title: "Fox in Socks", author: "Dr. Seuss") {
    title
    author {
      name
    }
  }
}

Đối với các truy vấn, máy chủ của chúng tôi sẽ phản hồi đột biến này với kết quả phù hợp với cấu trúc của đột biến, như sau:

{
  "data": {
    "addBook": {
      "title": "Fox in Socks",
      "author": {
        "name": "Dr. Seuss"
      }
    }
  }
}

Một yêu cầu của khách hàng có thể bao gồm nhiều đột biến để thực thi. Để ngăn chặn điều kiện chủng tộc, các đột biến được thực hiện tuần tự theo thứ tự được liệt kê.

Learn more about designing mutations

See Subscriptions.

Kiểu đầu vào là kiểu đối tượng đặc biệt cho phép bạn truyền các đối tượng làm đối số cho các truy vấn và đột biến (trái ngược với việc chỉ truyền các kiểu vô hướng). Các kiểu đầu vào giúp giữ cho chữ ký hoạt động sạch sẽ, giống như cách chấp nhận một đối tượng tùy chọn duy nhất trong một hàm JavaScript có thể rõ ràng hơn việc thêm nhiều lần các đối số vào chữ ký của hàm.

Hãy xem xét đột biến này tạo ra một bài đăng trên blog:

type Mutation {
  createPost(title: String, body: String, mediaUrls: [String]): Post
}

Thay vì chấp nhận ba đối số, đột biến này có thể chấp nhận một loại đầu vào duy nhất bao gồm tất cả các trường này. Điều này rất hữu ích nếu chúng tôi quyết định chấp nhận một lập luận bổ sung trong tương lai, chẳng hạn như tác giả.

Định nghĩa của kiểu đầu vào tương tự như kiểu của đối tượng, nhưng nó sử dụng từ khóa đầu vào:

type Mutation {
  createPost(post: PostAndMediaInput): Post
}

input PostAndMediaInput {
  title: String
  body: String
  mediaUrls: [String]
}

Điều này không chỉ tạo điều kiện thuận lợi cho việc chuyển loại PostAndMediaInput xung quanh trong lược đồ của chúng tôi, nó còn cung cấp cơ sở để chú thích các trường với mô tả được hiển thị tự động bởi các công cụ hỗ trợ GraphQL:

input PostAndMediaInput {
  "A main title for the post"
  title: String
  "The text body of the post."
  body: String
  "A list of URLs to render in the post."
  mediaUrls: [String]
}

Các kiểu đầu vào đôi khi có thể hữu ích khi nhiều thao tác yêu cầu cùng một bộ thông tin chính xác, nhưng bạn nên sử dụng lại chúng một cách tiết kiệm. Các hoạt động cuối cùng có thể khác nhau trong tập hợp các đối số bắt buộc của chúng.

Không sử dụng cùng một loại đầu vào cho cả truy vấn và đột biến. Trong nhiều trường hợp, các đối số được yêu cầu cho một đột biến là tùy chọn cho một truy vấn tương ứng.

Một enum tương tự như một kiểu vô hướng, nhưng các giá trị pháp lý của nó được xác định trong lược đồ. Đây là một định nghĩa ví dụ:

enum AllowedColor {
  RED
  GREEN
  BLUE
}

Enums hữu ích nhất trong các tình huống mà người dùng phải chọn từ một danh sách các tùy chọn được chỉ định. Như một lợi ích bổ sung, enum đánh giá cao tính năng tự động hoàn thành trong các công cụ như Apollo Studio Explorer.

Một enum có thể xuất hiện ở bất kỳ nơi nào mà một đại lượng vô hướng hợp lệ (bao gồm dưới dạng một đối số trường), bởi vì chúng tuần tự hóa dưới dạng chuỗi:

type Query {
  favoriteColor: AllowedColor # enum return value
  avatar(borderColor: AllowedColor): String # enum argument
}

Sau đó, một truy vấn có thể trông như thế này:

query GetAvatar {
  avatar(borderColor: RED)
}

Internal values (advanced)

Đôi khi, một chương trình phụ trợ buộc một giá trị khác cho một enum trong nội bộ so với trong API công khai. Bạn có thể đặt giá trị bên trong tương ứng của từng giá trị enum trong bản đồ trình phân giải mà bạn cung cấp cho Máy chủ Apollo.

Tính năng này thường không bắt buộc trừ khi một thư viện khác trong ứng dụng của bạn yêu cầu các giá trị enum ở một dạng khác.

Ví dụ sau sử dụng mã hex màu cho mỗi giá trị bên trong của AllowedColor:

const resolvers = {
  AllowedColor: {
    RED: '#f00',
    GREEN: '#0f0',
    BLUE: '#00f',
  }
  // ...other resolver definitions...
};

Các giá trị nội bộ này hoàn toàn không thay đổi API công khai. Các trình phân giải của Máy chủ Apollo chấp nhận các giá trị này thay vì các giá trị lược đồ, như được hiển thị:

const resolvers = {
  AllowedColor: {
    RED: '#f00',
    GREEN: '#0f0',
    BLUE: '#00f',
  },
  Query: {
    favoriteColor: () => '#f00',
    avatar: (parent, args) => {
      // args.borderColor is '#f00', '#0f0', or '#00f'
    },
  }
};

See Unions and interfaces.

Last updated

Navigation

Lionel

@Copyright 2023