Hướng dẫn bắt đầu GraphQL với Node.js (Phần 2)

2810

Phần 1 đã đã đề cập đến một số thuật ngữ khác nhau và một số tính năng kỹ thuật trong GraphQL. Tiếp theo sẽ là những thuật ngữ còn lại.

Aliases

Hãy tưởng tượng một tình huống mà chúng ta cần phải chọn hai người dùng khác nhau. Làm thế nào để chúng tôi xác định từng người dùng? Với GraphQL, bạn không thể truy vấn trực tiếp cho cùng một trường với các đối số khác nhau. Hãy cùng chứng tỏ nó.

Query

query getUsersWithAliasesError($userAID: Int!, $userBID: Int!) {
    user(id: $userAID) {
        name
        age
        gender
    },
    user(id: $userBID) {
        name
        age
        gender
    }
}

Variables

{ 
    "userAID":1,
    "userBID":2
}

Output

Lỗi này rất đặc tả và thậm chí sử dụng aliases. Hãy sửa lại nó.

query getUsersWithAliases($userAID: Int!, $userBID: Int!) {
    userA: user(id: $userAID) {
        name
        age
        gender
    },
    userB: user(id: $userBID) {
        name
        age
        gender
    }
}

Variables

{ 
    "userAID":1,
    "userBID":2
}

Output

Bây giờ chúng ta có thể xác định chính xác mỗi người dùng cùng các lĩnh vực của họ.

Fragment

Các truy vấn ở trên không phải là xấu, nhưng nó có một vấn đề; chúng ta đang lặp lại các trường tương tự cho cả userA và userB. Chúng ta có thể tìm thấy một cái gì đó sẽ làm cho ra các truy vấn DRY. GraphQL bao gồm các đơn vị có thể tái sử dụng được gọi là các fragment cho phép bạn xây dựng các tập các trường và tiếp theo gom chúng trong các truy vấn mà bạn cần.

Query

query getUsersWithFragments($userAID: Int!, $userBID: Int!) {
    userA: user(id: $userAID) {
        ...userFields
    },
    userB: user(id: $userBID) {
        ...userFields
    }
}

fragment userFields on Person {
  name
  age
  gender
}

Variables

{ 
    "userAID":1,
    "userBID":2
}

Output

Chúng tôi đã tạo ra một fragment được gọi là userFields chỉ có thể được áp dụng cho type Person và sử dụng nó để lấy người dùng.

Directives

Directive cho phép chúng tôi tự động thay đổi cấu trúc và hình dạng của các truy vấn mà sử dụng các biến. Tại một số điểm chúng ta có thể skip hoặc gom một số trường mà không thay đổi schema. Hai directive sẵn có là:

  • @include(if: Boolean) Chỉ bao gồm trường này trong kết quả nếu đối số đúng.
  • @skip(if: Boolean) Bỏ qua trường này nếu đối số đúng.

Let us say we want to retrieve users of gender ‘F’ but skip their age and include their id fields. We use variables to pass in the gender and use directives for the skipping and inclusion functionalities.

Hãy nói rằng chúng tôi muốn truy xuất người dùng giới tính ‘F’ nhưng bỏ qua tuổi và các trường id của họ. Chúng tôi sử dụng các biến để tìm ra giới tính và dùng các directive cho  chức năng skipping và inclusion.

Query

query getUsers($gender: String, $age: Boolean!, $id: Boolean!) {
  users(gender: $gender){
    ...userFields
  }
}

fragment userFields on Person {
  name
  age @skip(if: $age)
  id @include(if: $id)
}

Variables

{
  "gender": "F",
  "age": true,
  "id": true
}

Output

Mutations

Cho đến nay chúng tôi đã giải quyết các thắc mắc; hoạt động để retrieve dữ liệu. Mutation là hoạt động chính thứ hai trong GraphQL nhằm tạo, xoá và cập nhật dữ liệu. Hãy tập trung vào một số ví dụ về cách thực hiện đột biến. Ví dụ: chúng tôi muốn cập nhật người dùng có id==1 và thay đổi độ tuổi của họ theo tên và độ tuổi và trả lại chi tiết user mới.

Chúng tôi sẽ cập nhật schema để bao gồm một loại mutation và cũng cập nhật root resolve với các chức năng resolve liên quan.

// Add mutations
var schema = buildSchema(`
  ...
  type Mutation {
    updateUser(id: Int!, name: String!, age: String): Person
  }
`);
...
var updateUser = function({id, name, age}) {  // Update a user and return new user details
  users.map(user => {
    if(user.id === id) {
      user.name = name;
      user.age = age;
      return user;
    }
  });
  return users.filter(user=> user.id === id) [0];
}
...

var root = { 
  user: getUser,
  users: retrieveUsers,
  updateUser: updateUser  // Include mutation function in root resolver
};

Giả sử đây là những chi tiết người dùng đầu.

Sau mutation để cập nhật user, chúng tôi nhận được các chi tiết của user mới.

Query

mutation updateUser($id: Int!, $name: String!, $age: String) {
  updateUser(id: $id, name:$name, age: $age){
    ...userFields
  }
}
fragment userFields on Person {
  name
  age
  gender
}

Variables

{
  "id": 1,
  "name": "Keavin",
  "age": "27"
}

#Conclusion

Cho đến nay, chúng ta đã biết đến các khái niệm cơ bản về GraphQL với một số ví dụ  phức tạp. Hầu hết các ví dụ này cho thấy rõ sự khác biệt giữa GraphQL và REST đối với người dùng đã tương tác với REST.

TopDev via Scotch