แชร์ผ่าน


TripPin ตอนที่ 5 - เพจจิ้ง

บทช่วยสอนแบบหลายส่วนนี้ครอบคลุมการสร้างส่วนขยายแหล่งข้อมูลใหม่สําหรับ Power Query บทช่วยสอนมีไว้ให้ทําตามลําดับ—แต่ละบทเรียนจะสร้างขึ้นจากตัวเชื่อมต่อที่สร้างขึ้นในบทเรียนก่อนหน้า โดยจะเพิ่มความสามารถใหม่ให้กับตัวเชื่อมต่อของคุณทีละน้อย

ในบทเรียนนี้ คุณ:

  • เพิ่มการสนับสนุนการแบ่งหน้าไปยังตัวเชื่อมต่อ

Rest API จํานวนมากส่งคืนข้อมูลใน "หน้า" ซึ่งกําหนดให้ไคลเอ็นต์ต้องส่งคําขอหลายรายการเพื่อรวมผลลัพธ์เข้าด้วยกัน แม้ว่าจะมีข้อตกลงทั่วไปบางประการสําหรับการแบ่งหน้า (เช่น RFC 5988) แต่โดยทั่วไปจะแตกต่างกันไปในแต่ละ API โชคดีที่ TripPin เป็นบริการ OData และ มาตรฐาน OData กําหนดวิธีการแบ่งหน้าโดยใช้ค่า odata.nextLink ที่ส่งคืนในเนื้อหาของการตอบกลับ

เพื่อลดความซับซ้อนของการทําซ้ําก่อนหน้านี้ของตัวเชื่อมต่อ ฟังก์ชันจะไม่TripPin.Feedรับรู้หน้า มันเพียงแค่แยกวิเคราะห์ JSON ที่ส่งคืนจากคําขอและจัดรูปแบบเป็นตาราง หากคุณคุ้นเคยกับโปรโตคอล OData คุณอาจสังเกตเห็นว่ามีสมมติฐานที่ไม่ถูกต้องมากมายเกี่ยวกับ รูปแบบของการตอบกลับ (เช่น สมมติว่ามี value ฟิลด์ที่มีอาร์เรย์ของเรกคอร์ด)

ในบทเรียนนี้ คุณจะปรับปรุงตรรกะการจัดการการตอบกลับของคุณโดยทําให้เป็นการรับรู้หน้าเว็บ บทช่วยสอนในอนาคตทําให้ตรรกะการจัดการหน้าเว็บมีประสิทธิภาพมากขึ้นและสามารถจัดการรูปแบบการตอบกลับได้หลายรูปแบบ (รวมถึงข้อผิดพลาดจากบริการ)

Note

คุณไม่จําเป็นต้องใช้ตรรกะการเพจของคุณเองด้วยตัวเชื่อมต่อที่อิงตาม OData.Feed เนื่องจากจะจัดการทั้งหมดให้คุณโดยอัตโนมัติ

รายการตรวจสอบเพจ

เมื่อใช้การสนับสนุนเพจจิ้ง คุณจําเป็นต้องทราบสิ่งต่อไปนี้เกี่ยวกับ API ของคุณ:

  • คุณจะขอข้อมูลหน้าถัดไปได้อย่างไร
  • กลไกการเพจเกี่ยวข้องกับการคํานวณค่าหรือไม่ หรือคุณแยก URL สําหรับหน้าถัดไปจากการตอบกลับ
  • คุณจะรู้ได้อย่างไรว่าเมื่อใดควรหยุดเพจ
  • มีพารามิเตอร์ที่เกี่ยวข้องกับการเพจที่คุณควรทราบหรือไม่ (เช่น "ขนาดหน้า")

คําตอบสําหรับคําถามเหล่านี้ส่งผลต่อวิธีที่คุณใช้ตรรกะการเพจของคุณ แม้ว่าจะมีการนําโค้ดกลับมาใช้ใหม่จํานวนหนึ่งในการใช้งานเพจ (เช่น การใช้ Table.GenerateByPage) ตัวเชื่อมต่อส่วนใหญ่จบลงด้วยตรรกะแบบกําหนดเอง

Note

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

ภาพรวมของ OData Paging

การเพจ OData ขับเคลื่อนโดย คําอธิบายประกอบ nextLink ที่มีอยู่ภายในเพย์โหลดการตอบสนอง ค่า nextLink ประกอบด้วย URL ไปยังหน้าถัดไปของข้อมูล เมื่อต้องการตรวจสอบว่ามีหน้าข้อมูลอื่นหรือไม่ ให้มองหา odata.nextLink เขตข้อมูลในวัตถุด้านนอกสุดในการตอบกลับ ถ้าไม่มี odata.nextLink ฟิลด์ ข้อมูลทั้งหมดของคุณจะถูกอ่าน

{
  "odata.context": "...",
  "odata.count": 37,
  "value": [
    { },
    { },
    { }
  ],
  "odata.nextLink": "...?$skiptoken=342r89"
}

บริการ OData บางอย่างอนุญาตให้ไคลเอ็นต์ระบุ การตั้งค่าขนาดหน้าสูงสุด แต่ขึ้นอยู่กับบริการว่าจะให้เกียรติหรือไม่ Power Query ควรจะสามารถจัดการการตอบกลับทุกขนาด ดังนั้นคุณจึงไม่ต้องกังวลเกี่ยวกับการระบุการกําหนดลักษณะขนาดหน้า คุณสามารถสนับสนุนสิ่งที่บริการโยนให้คุณได้

ข้อมูลเพิ่มเติมเกี่ยวกับ เพจServer-Driven สามารถพบได้ในข้อมูลจําเพาะของ OData

การทดสอบ TripPin

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

let
    source = TripPin.Contents(),
    data = source{[Name="People"]}[Data],
    withRowCount = Table.AddIndexColumn(data, "Index")
in
    withRowCount

เปิด Fiddler และเรียกใช้คิวรีใน Power Query SDK แบบสอบถามจะส่งกลับตารางที่มีแปดแถว (ดัชนี 0 ถึง 7)

สกรีนช็อตของแท็บผลลัพธ์ของผลลัพธ์ PQTest ที่แสดงตารางที่มีแถวดัชนี 0 ถึง 7

หากคุณดูเนื้อหาของการตอบกลับจาก fiddler ในความเป็นจริง @odata.nextLink แล้วมีฟิลด์ซึ่งบ่งชี้ว่ามีหน้าข้อมูลเพิ่มเติม

{
  "@odata.context": "https://services.odata.org/V4/TripPinService/$metadata#People",
  "@odata.nextLink": "https://services.odata.org/v4/TripPinService/People?%24skiptoken=8",
  "value": [
    { },
    { },
    { }
  ]
}

การใช้เพจจิ้งสําหรับ TripPin

ตอนนี้ทําการเปลี่ยนแปลงต่อไปนี้กับส่วนขยายของคุณ:

  1. นําเข้าฟังก์ชันทั่วไปTable.GenerateByPage
  2. เพิ่ม GetAllPagesByNextLink ฟังก์ชันที่ใช้ Table.GenerateByPage ในการติดกาวทุกหน้าเข้าด้วยกัน
  3. เพิ่ม GetPage ฟังก์ชันที่สามารถอ่านข้อมูลหน้าเดียวได้
  4. เพิ่ม GetNextLink ฟังก์ชันเพื่อแยก URL ถัดไปจากการตอบกลับ
  5. อัปเดต TripPin.Feed เพื่อใช้ฟังก์ชันตัวอ่านหน้าใหม่

Note

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

ตาราง.สร้างตามหน้า

เมื่อต้องการรวมหลายหน้า (ที่อาจ) ส่งคืนโดยแหล่งที่มาเป็นตารางเดียว ให้ใช้Table.GenerateByPage ฟังก์ชันนี้ใช้ฟังก์ชันที่ควรทําตามชื่อของมันเป็นอาร์กิว getNextPage เมนต์: ดึงข้อมูลหน้าถัดไป Table.GenerateByPage เรียก getNextPage ฟังก์ชันซ้ําๆ ทุกครั้งที่ส่งผ่านผลลัพธ์ที่เกิดขึ้นในครั้งสุดท้ายที่มีการเรียก จนกว่าจะกลับมา null ส่งสัญญาณกลับว่าไม่มีหน้าว่างอีกต่อไป

เนื่องจากฟังก์ชันนี้ไม่ได้เป็นส่วนหนึ่งของไลบรารีมาตรฐานของ Power Query คุณจึงต้องคัดลอก ซอร์สโค้ด ลงในไฟล์ .pq ของคุณ

เนื้อหาของฟังก์ชันของคุณ GetAllPagesByNextLink ใช้ getNextPage อาร์กิวเมนต์ฟังก์ชันสําหรับ Table.GenerateByPage. มันเรียก GetPage ฟังก์ชัน และดึงข้อมูล URL สําหรับหน้าถัดไปของข้อมูลจาก NextLink ฟิลด์ของเรกคอร์ด meta จากการเรียกก่อนหน้า

// Read all pages of data.
// After every page, we check the "NextLink" record on the metadata of the previous request.
// Table.GenerateByPage will keep asking for more pages until we return null.
GetAllPagesByNextLink = (url as text) as table =>
    Table.GenerateByPage((previous) => 
        let
            // if previous is null, then this is our first page of data
            nextLink = if (previous = null) then url else Value.Metadata(previous)[NextLink]?,
            // if NextLink was set to null by the previous call, we know we have no more data
            page = if (nextLink <> null) then GetPage(nextLink) else null
        in
            page
    );

การใช้งาน GetPage

ฟังก์ชันของคุณ GetPage ใช้ Web.Contents เพื่อดึงข้อมูลหน้าเดียวจากบริการ TripPin และแปลงการตอบกลับเป็นตาราง มันส่งผ่านการตอบสนองจาก Web.Contents ไปยัง GetNextLink ฟังก์ชันเพื่อแยก URL ของหน้าถัดไป และตั้งค่าไว้ใน meta เรกคอร์ดของตารางที่ส่งคืน (หน้าข้อมูล)

การใช้งานนี้เป็นเวอร์ชันที่แก้ไขเล็กน้อยของการ TripPin.Feed เรียกจากบทช่วยสอนก่อนหน้านี้

GetPage = (url as text) as table =>
    let
        response = Web.Contents(url, [ Headers = DefaultRequestHeaders ]),        
        body = Json.Document(response),
        nextLink = GetNextLink(body),
        data = Table.FromRecords(body[value])
    in
        data meta [NextLink = nextLink];

ฟังก์ชันของคุณ GetNextLink เพียงแค่ตรวจสอบเนื้อหาของการตอบสนองสําหรับ @odata.nextLink ฟิลด์ และส่งคืนค่าของฟิลด์

// In this implementation, 'response' is the parsed body of the response after the call to Json.Document.
// Look for the '@odata.nextLink' field and simply return null if it doesn't exist.
GetNextLink = (response) as nullable text => Record.FieldOrDefault(response, "@odata.nextLink");

รวมทุกอย่างเข้าด้วยกัน

ขั้นตอนสุดท้ายในการใช้ตรรกะการเพจของคุณคือการอัปเดต TripPin.Feed เพื่อใช้ฟังก์ชันใหม่ สําหรับตอนนี้ คุณเพียงแค่เรียก GetAllPagesByNextLinkผ่านไปที่ แต่ในบทช่วยสอนที่ตามมา คุณกําลังเพิ่มความสามารถใหม่ (เช่น การบังคับใช้ Schema และตรรกะพารามิเตอร์คิวรี)

TripPin.Feed = (url as text) as table => GetAllPagesByNextLink(url);

ถ้าคุณเรียกใช้ คิวรีทดสอบ เดียวกันจากก่อนหน้านี้ในบทช่วยสอน คุณควรเห็นโปรแกรมอ่านหน้าทํางาน คุณควรเห็นว่าคุณมี 24 แถวในการตอบกลับแทนที่จะเป็นแปดแถว

สกรีนช็อตของแท็บเอาต์พุตของผลลัพธ์ PQTest ที่แสดงข้อมูล 24 แถว

หากคุณดูคําขอใน fiddler ตอนนี้คุณควรเห็นคําขอแยกต่างหากสําหรับข้อมูลแต่ละหน้า

ภาพหน้าจอของเอาต์พุต Fiddler พร้อมคําขอแยกต่างหากสําหรับข้อมูลแต่ละหน้า

Note

คุณอาจสังเกตเห็นคําขอที่ซ้ํากันสําหรับหน้าแรกของข้อมูลจากบริการ ซึ่งไม่เหมาะ คําขอเพิ่มเติมเป็นผลมาจากลักษณะการตรวจสอบ Schema ของกลไกจัดการ M ละเว้นปัญหานี้ในตอนนี้ และแก้ไขใน บทช่วยสอนถัดไป ซึ่งคุณใช้สคีมาที่ชัดเจน

บทสรุป

บทเรียนนี้แสดงวิธีใช้การสนับสนุนการแบ่งหน้าสําหรับ Rest API แม้ว่าตรรกะจะแตกต่างกันไปตาม API แต่รูปแบบที่สร้างขึ้นที่นี่ควรนํากลับมาใช้ใหม่ได้ด้วยการปรับเปลี่ยนเล็กน้อย

ในบทเรียนถัดไป คุณจะดูวิธีใช้ Schema ที่ชัดเจนกับข้อมูลของคุณ โดยนอกเหนือจากประเภทข้อมูลธรรมดาtextและnumberประเภทข้อมูลที่คุณได้รับจากJson.Document

ขั้นตอนถัดไป

TripPin ตอนที่ 6 - Schema