จะค้นหาฟิลด์ประเภท GraphQL ทั้งหมดโดยไม่ต้องเขียนแบบสอบถามยาว ๆ ได้อย่างไร?


131

สมมติว่าคุณมีประเภท GraphQL และมีหลายฟิลด์ จะสอบถามทุกช่องได้อย่างไรโดยไม่ต้องเขียนแบบสอบถามยาว ๆ ที่มีชื่อของเขตข้อมูลทั้งหมด

ตัวอย่างเช่นหากฉันมีฟิลด์เหล่านี้:

 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'
            ]

        ];
    }

ในการสืบค้นเขตข้อมูลทั้งหมดโดยปกติแบบสอบถามจะเป็นดังนี้:

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

แต่ฉันต้องการวิธีที่จะได้ผลลัพธ์เดียวกันโดยไม่ต้องเขียนฟิลด์ทั้งหมดเช่นนี้:

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

มีวิธีทำใน GraphQL ไหม ??

ฉันใช้ไลบรารีFolkloreatelier / laravel-graphql


4
คุณกำลังถามวิธีทำบางสิ่งที่ GraphQL โดยการออกแบบไม่รองรับ
Travis Webb

12
เพียงพิมพ์ฟิลด์เหล่านั้น 40 ช่องและหวังว่าคุณจะไม่พิมพ์ผิด :)
สกา

33
ว้าวฉันเพิ่งเริ่มต้นใน GraphQL และนี่คือ WTF ที่จริงจัง
user949300

1
มันสมเหตุสมผลแล้วที่ไม่ได้รับการสนับสนุนลองนึกภาพว่าคุณมีอ็อบเจกต์ Student และ Class นักเรียนมี "คลาส" ฟิลด์ที่แสดงรายชื่อคลาสทั้งหมดที่เขาเข้าร่วมคลาสมี "นักเรียน" ฟิลด์ที่แสดงรายชื่อนักเรียนทั้งหมดที่เข้าร่วมชั้นเรียนนั้น นั่นคือโครงสร้างที่เป็นวัฏจักร ตอนนี้ถ้าคุณขอนักเรียนทุกคนที่มีทุกสาขานั่นจะรวมทุกสาขาของชั้นเรียนที่ส่งคืนด้วยหรือไม่? และชั้นเรียนเหล่านั้นมีนักเรียนจะรวมสาขาของพวกเขาด้วยหรือไม่? และนักเรียนมีเรียน ...
Buksy

ฉันมีคำถามนี้และเพื่อที่ฉันจะได้เห็นว่ามีอะไรให้ดึงได้บ้าง ไคลเอนต์ GraphQL จำนวนมาก (เช่น GraphiQL ดูที่gatsbyjs.org/docs/running-queries-with-graphiql ) มี schema explorer ที่ใช้วิปัสสนาเพื่อนำเสนอสิ่งที่คุณสามารถดึงได้หากนั่นเป็นเหตุผลเบื้องหลังที่ต้องการได้รับ "ทุกอย่าง "
James

คำตอบ:


121

ขออภัยสิ่งที่คุณต้องการทำไม่สามารถทำได้ GraphQL ต้องการให้คุณระบุอย่างชัดเจนเกี่ยวกับการระบุฟิลด์ที่คุณต้องการส่งคืนจากการสืบค้นของคุณ


5
ตกลงและถ้าฉันขอวัตถุบางอย่างในรูปแบบที่ไม่รู้จักจากแบ็กเอนด์ซึ่งฉันควรจะพร็อกซีหรือส่งกลับ?
meandre

19
@meandre แนวคิดทั้งหมดของ graphql คือไม่มีสิ่งที่เรียกว่า "รูปแบบที่ไม่รู้จัก"
s.meijer

2
@meandre คำตอบของฉันด้านล่างอาจเป็นประโยชน์สำหรับคุณ?
Tyrone Wilson

มันเป็นแนวคิดทั้งหมดของภาษาและโปรโตคอลการสืบค้น API ส่วนใหญ่ไม่ใช่หรือ, @meandre
Clijsters

น่าสนใจจริงๆมันเป็นความคิดที่แตกต่างเมื่อใช้ graphql
andy mccullough

91

ใช่คุณสามารถทำได้โดยใช้วิปัสสนา สร้างแบบสอบถาม GraphQL เช่น (สำหรับประเภทUserType )

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

และคุณจะได้รับคำตอบเช่น (ชื่อฟิลด์จริงจะขึ้นอยู่กับข้อกำหนดสคีมา / ประเภทจริงของคุณ)

{
  "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. ...)
      ]
    }
  }
}

จากนั้นคุณสามารถอ่านรายการฟิลด์นี้ในไคลเอนต์ของคุณและสร้างแบบสอบถาม GraphQL ที่สองแบบไดนามิกเพื่อรับฟิลด์เหล่านี้ทั้งหมด

สิ่งนี้ขึ้นอยู่กับว่าคุณรู้ชื่อประเภทที่คุณต้องการรับฟิลด์สำหรับ - หากคุณไม่ทราบประเภทคุณสามารถรวมประเภทและฟิลด์ทั้งหมดเข้าด้วยกันโดยใช้การวิปัสสนาเช่น

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

หมายเหตุ: นี่เป็นข้อมูล GraphQL แบบ over-the-wire - คุณเป็นคนคิดเองว่าจะอ่านและเขียนกับลูกค้าจริงของคุณอย่างไร ไลบรารี javascript ของ graphQL อาจใช้การวิปัสสนาในความสามารถบางอย่างอยู่แล้วเช่นคำสั่งapollo codegenใช้วิปัสสนาเพื่อสร้างประเภท


ดูเหมือนว่าเราควรแสดงความใส่ใจเกี่ยวกับประเภทการเรียกซ้ำ หากคุณเดินลงไปบนต้นไม้และชนกับประเภทที่มีตัวมันเองในบางรูปแบบ (รายการเดี่ยวหรืออื่น ๆ .. ) คุณอาจอยู่ในการเรียกซ้ำแบบไม่สิ้นสุด
Milos Grujic

นั่นไม่ได้เกิดขึ้นจริงจากประสบการณ์ของฉันกับการสืบค้นนี้โดยเฉพาะ - แบบสอบถามนั้นกำหนดความลึกของความละเอียด
Mark Chackerian

คำตอบข้างต้นอนุญาตให้คุณค้นหาเฉพาะประเภทของเขตข้อมูลที่มีอยู่ในแบบสอบถามเท่านั้น จะไม่ส่งคืนค่า "ค่า" ในช่องวัตถุทั้งหมดซึ่งเป็นคำถามเดิมเกี่ยวกับ
quantdaddy

4
ตามคำตอบคุณต้องสร้างแบบสอบถามที่สองแบบไดนามิกตามผลลัพธ์ของแบบสอบถามแรก - ฉันทิ้งไว้เป็นแบบฝึกหัดสำหรับผู้อ่าน
Mark Chackerian

39

ฉันเดาว่าวิธีเดียวที่จะทำได้คือการใช้ชิ้นส่วนที่ใช้ซ้ำได้:

fragment UserFragment on Users {
    id
    username
    count
} 

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

19
ถ้าฉันทำอย่างนั้นฉันก็ยังต้องเขียนชื่อฟิลด์แต่ละฟิลด์ "อย่างน้อยก็ในส่วน" แม่มดสิ่งที่ฉันพยายามหลีกเลี่ยงดูเหมือนว่า GraphQL บังคับให้เราต้องชัดเจน
BlackSigma

จะเพิ่มสิ่งนี้ในแบบสอบถาม POSTMan ได้อย่างไร? หรือ jquery / UI framwork เพื่อสร้าง JSON แบบสตริง graphiQL นี้ดูเหมือนไม่มีประโยชน์สำหรับวัตถุประสงค์ในการพัฒนาจริง
mfaisalhyder

นี่เป็นเพียงวัตถุประสงค์ในการนำกลับมาใช้ใหม่เท่านั้น
Henok Tesfaye

@BlackSigma เมื่อพิจารณาจากเอกสาร GraphQLสิ่งนี้ควรได้รับการยอมรับว่าเป็นคำตอบที่ดีที่สุด
JP Ventura

4
@JPVentura: ไม่มีเพื่อนของฉันมีความแตกต่างระหว่างการใช้ซ้ำและสัญลักษณ์แทนทั้งในแนวคิดและการใช้งาน จุดประสงค์ของการแยกส่วนมีความชัดเจนในเอกสาร "GraphQL ประกอบด้วยหน่วยที่ใช้ซ้ำได้ที่เรียกว่าแฟรกเมนต์" การใช้แฟรกเมนต์มีประโยชน์ แต่ไม่ใช่คำตอบสำหรับคำถาม
BlackSigma

11

ฉันประสบปัญหาเดียวกันนี้เมื่อฉันต้องการโหลดข้อมูลตำแหน่งที่ฉันจัดลำดับไว้ในฐานข้อมูลจาก google places API โดยทั่วไปฉันต้องการให้ทุกอย่างทำงานร่วมกับแผนที่ได้ แต่ฉันไม่ต้องการระบุฟิลด์ทั้งหมดทุกครั้ง

ฉันทำงานใน Ruby ดังนั้นฉันจึงไม่สามารถให้การใช้งาน PHP แก่คุณได้ แต่หลักการควรจะเหมือนกัน

ฉันกำหนดประเภทสเกลาร์แบบกำหนดเองที่เรียกว่า JSON ซึ่งจะส่งคืนอ็อบเจ็กต์ JSON ตามตัวอักษร

การใช้ทับทิมเป็นเช่นนั้น (โดยใช้ graphql-ruby)

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

จากนั้นฉันก็ใช้มันสำหรับวัตถุของเราเช่นนั้น

field :location, Types::JsonType

ฉันจะใช้สิ่งนี้เท่าที่จำเป็นโดยใช้เฉพาะที่ที่คุณรู้ว่าคุณต้องการวัตถุ JSON ทั้งหมดเสมอ (อย่างที่ฉันทำในกรณีของฉัน) มิฉะนั้นจะเป็นการเอาชนะวัตถุของ GraphQL โดยทั่วไปแล้ว


1
นี่คือสิ่งที่ฉันต้องการขอบคุณ กรณีการใช้งานของฉันคือฉันมีสตริงใช้แปลตลอดทั้งระบบและพวกเขาจะถูกเก็บเป็น JSON {"en": "Hello", "es": "Hola"}ในฐานข้อมูลเช่น และเนื่องจากผู้ใช้แต่ละคนสามารถใช้ภาษาย่อยของตนเองสำหรับกรณีการใช้งานของตนจึงไม่สมเหตุสมผลที่ UI จะสืบค้นทุกชุดย่อยที่เป็นไปได้ ตัวอย่างของคุณทำงานได้อย่างสมบูรณ์
Luke Ehresman

2

รูปแบบการสืบค้น GraphQLได้รับการออกแบบเพื่อให้:

  1. ทั้งแบบสอบถามและรูปร่างผลลัพธ์เหมือนกันทุกประการ
  2. เซิร์ฟเวอร์รู้ว่าฟิลด์ที่ร้องขอดังนั้นไคลเอนต์จึงดาวน์โหลดเฉพาะข้อมูลที่จำเป็นเท่านั้น

อย่างไรก็ตามตามเอกสาร GraphQLคุณสามารถสร้างชิ้นส่วนเพื่อให้ชุดการเลือกใช้ซ้ำได้มากขึ้น:

# Only most used selection properties

fragment UserDetails on User {
    id,
    username
} 

จากนั้นคุณสามารถสอบถามรายละเอียดผู้ใช้ทั้งหมดโดย:

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

คุณยังสามารถเพิ่มฟิลด์เพิ่มเติมข้างส่วนของคุณ :

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.