Làm cách nào để truy vấn tất cả các trường kiểu GraphQL mà không cần viết một truy vấn dài?


130

Giả sử bạn có kiểu GraphQL và nó bao gồm nhiều trường. Làm thế nào để truy vấn tất cả các trường mà không cần viết ra một truy vấn dài bao gồm tên của tất cả các trường?

Ví dụ: Nếu tôi có các trường này:

 public function fields()
    {
        return [
            'id' => [
                'type' => Type::nonNull(Type::string()),
                'description' => 'The id of the user'
            ],
            'username' => [
                'type' => Type::string(),
                'description' => 'The email of user'
            ], 
             'count' => [
                'type' => Type::int(),
                'description' => 'login count for the user'
            ]

        ];
    }

Để truy vấn tất cả các trường, thường thì truy vấn là như sau:

FetchUsers{users(id:"2"){id,username,count}}

Nhưng tôi muốn một cách để có cùng kết quả mà không cần viết tất cả các trường, đại loại như sau:

FetchUsers{users(id:"2"){*}}
//or
FetchUsers{users(id:"2")}

Có cách nào để làm điều này trong GraphQL không ??

Tôi đang sử dụng thư viện Folkloreatelier / laravel-graphql .


4
Bạn đang hỏi cách thực hiện điều gì đó mà GraphQL, theo thiết kế, không hỗ trợ.
Travis Webb

12
Chỉ cần gõ 40 trường gì đó và hy vọng bạn không mắc lỗi chính tả :)
Ska

32
Chà, tôi mới bắt đầu với GraphQL, và đây là một WTF nghiêm túc.
user949300

1
Có nghĩa là nó không được hỗ trợ, hãy tưởng tượng bạn có các đối tượng Sinh viên và Lớp học, sinh viên có trường "lớp" liệt kê tất cả các lớp học mà anh ta tham dự, lớp có trường "sinh viên" liệt kê tất cả sinh viên tham dự lớp học đó. Đó là một cấu trúc tuần hoàn. Bây giờ nếu bạn yêu cầu cho tất cả sinh viên với tất cả các trường, thì điều đó cũng bao gồm tất cả các trường của lớp học được trả về? Và những lớp học đó có sinh viên, các lĩnh vực của họ có được bao gồm không? Và sinh viên có các lớp học, ...
Buksy

Tôi đã có câu hỏi này và nó là để tôi có thể thấy những gì thậm chí có sẵn để kéo. Rất nhiều máy khách GraphQL (ví dụ: GraphiQL, xem gatsbyjs.org/docs/running-queries-with-graphiql ) có trình khám phá lược đồ sử dụng phần nội quan để trình bày cho bạn những gì bạn có thể kéo, nếu đó là lý do đằng sau việc muốn có được "mọi thứ ".
James

Câu trả lời:


120

Thật không may, những gì bạn muốn làm là không thể. GraphQL yêu cầu bạn phải rõ ràng về việc chỉ định trường nào bạn muốn trả về từ truy vấn của mình.


5
Được, và nếu tôi yêu cầu một số đối tượng có dạng không xác định từ chương trình phụ trợ mà tôi phải ủy quyền hoặc gửi lại?
mondre

19
@meandre, toàn bộ ý tưởng của graphql là không có cái gọi là "dạng chưa xác định".
s.meijer

2
@meandre, Câu trả lời của tôi dưới đây có thể hữu ích cho bạn không?
Tyrone Wilson

Đó không phải là toàn bộ ý tưởng về hầu hết các giao thức và ngôn ngữ truy vấn API sao ?, @meandre
Clijsters

thú vị, đó thực sự là một suy nghĩ khác khi sử dụng graphql
andy mccullough

91

Có, bạn có thể làm điều này bằng cách sử mẫn . Tạo một truy vấn GraphQL như (đối với loại UserType )

{
   __type(name:"UserType") {
      fields {
         name
         description
      }  
   }
}

và bạn sẽ nhận được phản hồi như (tên trường thực tế sẽ phụ thuộc vào định nghĩa lược đồ / loại thực tế của bạn)

{
  "data": {
    "__type": {
      "fields": [
        {
          "name": "id",
          "description": ""
        },
        {
          "name": "username",
          "description": "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only."
        },
        {
          "name": "firstName",
          "description": ""
        },
        {
          "name": "lastName",
          "description": ""
        },
        {
         "name": "email",
          "description": ""
        },
        ( etc. etc. ...)
      ]
    }
  }
}

Sau đó, bạn có thể đọc danh sách các trường này trong máy khách của mình và tạo động một truy vấn GraphQL thứ hai để lấy tất cả các trường này.

Điều này phụ thuộc vào việc bạn biết tên của loại mà bạn muốn lấy các trường - nếu bạn không biết loại, bạn có thể lấy tất cả các loại và trường cùng nhau bằng cách sử dụng nội dung như

{
  __schema {
    types {
      name
      fields {
        name
        description
      }
    }
  }
}

LƯU Ý: đây là dữ liệu GraphQL qua dây - bạn phải tự tìm cách đọc và ghi với khách hàng thực tế của mình. Thư viện javascript graphQL của bạn có thể đã sử dụng nội quan trong một số khả năng, ví dụ: lệnh apollo codegen sử dụng nội quan để tạo các loại.


Có vẻ như một người nên quan tâm đến các loại đệ quy. Nếu bạn đi xuống cái cây và chạm vào một loại có chứa chính nó, ở một số dạng (danh sách, đơn lẻ hoặc khác ..), bạn có thể tham gia vào một đệ quy vô hạn.
Milos Grujic

Điều đó không thực sự xảy ra theo kinh nghiệm của tôi với truy vấn cụ thể này - chính truy vấn xác định độ sâu độ phân giải.
Mark Chackerian

Câu trả lời trên chỉ cho phép bạn truy vấn các loại trường có sẵn trong một truy vấn. Nó không trả về tất cả các trường đối tượng "giá trị", đó là những gì câu hỏi ban đầu là về.
quantdaddy

4
Theo câu trả lời, bạn phải tạo động truy vấn thứ hai dựa trên kết quả của truy vấn đầu tiên - tôi để đó như một bài tập cho người đọc.
Mark Chackerian

39

Tôi đoán cách duy nhất để làm điều này là sử dụng các đoạn có thể tái sử dụng:

fragment UserFragment on Users {
    id
    username
    count
} 

FetchUsers {
    users(id: "2") {
        ...UserFragment
    }
}

19
Nếu tôi đã làm điều đó, thì tôi vẫn phải viết mỗi tên trường "ít nhất là trong phân đoạn", phù hợp với những gì tôi đang cố gắng tránh, có vẻ như GraphQL buộc chúng ta phải rõ ràng.
BlackSigma

làm thế nào để thêm điều này vào một truy vấn POSTMan? hoặc jquery / UI framwork để tạo JSON được xâu chuỗi. GraphiQL này dường như vô dụng cho mục đích phát triển thực tế.
mfaisalhyder

Điều này chỉ dành cho mục đích tái sử dụng.
Henok Tesfaye vào

@BlackSigma Xét tài liệu GraphQL , điều này sẽ được các chấp nhận như là câu trả lời tốt nhất
JP Ventura

4
@JPVentura: Không bạn ơi, có sự khác biệt giữa khả năng tái sử dụng và ký tự đại diện cả về khái niệm và ứng dụng. Mục đích phân mảnh rõ ràng trong tài liệu "GraphQL bao gồm các đơn vị có thể tái sử dụng được gọi là phân mảnh." Sử dụng phân mảnh là hữu ích, nhưng không phải là câu trả lời cho câu hỏi.
BlackSigma

11

Tôi cũng gặp phải vấn đề này khi cần tải dữ liệu vị trí mà tôi đã tuần tự hóa vào cơ sở dữ liệu từ API địa điểm của google. Nói chung, tôi muốn toàn bộ mọi thứ để nó hoạt động với bản đồ nhưng tôi không muốn phải chỉ định tất cả các trường mọi lúc.

Tôi đang làm việc trong Ruby nên tôi không thể cung cấp cho bạn cách triển khai PHP nhưng nguyên tắc phải giống nhau.

Tôi đã xác định một loại vô hướng tùy chỉnh được gọi là JSON chỉ trả về một đối tượng JSON theo nghĩa đen.

Việc triển khai ruby ​​giống như vậy (sử dụng graphql-ruby)

module Graph
  module Types
    JsonType = GraphQL::ScalarType.define do
      name "JSON"
      coerce_input -> (x) { x }
      coerce_result -> (x) { x }
    end
  end
end

Sau đó, tôi sử dụng nó cho các đối tượng của chúng tôi như vậy

field :location, Types::JsonType

Mặc dù vậy, tôi sẽ sử dụng điều này rất ít, chỉ sử dụng nó khi bạn biết rằng bạn luôn cần toàn bộ đối tượng JSON (như tôi đã làm trong trường hợp của mình). Nếu không, nó đang đánh bại đối tượng của GraphQL nói chung.


1
Đây là chính xác những gì tôi cần, cảm ơn bạn. Trường hợp sử dụng của tôi là tôi có các chuỗi người dùng có thể dịch được trong toàn bộ hệ thống và chúng được lưu trữ dưới dạng json trong db giống như vậy {"en": "Hello", "es": "Hola"}. Và vì mỗi người dùng có thể triển khai tập hợp con ngôn ngữ của riêng họ cho trường hợp sử dụng của họ, giao diện người dùng không có ý nghĩa gì khi truy vấn mọi tập hợp con có thể có. Ví dụ của bạn hoạt động hoàn hảo.
Luke Ehresman

2

Định dạng truy vấn GraphQL được thiết kế để cho phép:

  1. Cả hình dạng truy vấn và kết quả đều hoàn toàn giống nhau .
  2. Máy chủ biết chính xác các trường được yêu cầu, do đó máy khách chỉ tải xuống dữ liệu cần thiết.

Tuy nhiên, theo tài liệu GraphQL , bạn có thể tạo các phân đoạn để làm cho các bộ lựa chọn có thể tái sử dụng nhiều hơn:

# Only most used selection properties

fragment UserDetails on User {
    id,
    username
} 

Sau đó, bạn có thể truy vấn tất cả chi tiết người dùng bằng cách:

FetchUsers {
    users() {
        ...UserDetails
    }
}

Bạn cũng có thể thêm các trường bổ sung cùng với phân đoạn của mình :

FetchUserById($id: ID!) {
    users(id: $id) {
        ...UserDetails
        count
    }
}

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.