TripPin ส่วนที่ 5 - การแบ่งหน้า
บทช่วยสอนแบบหลายส่วนนี้ครอบคลุมการสร้างส่วนขยายแหล่งข้อมูลใหม่สําหรับ Power Query บทช่วยสอนมีไว้ให้ทําตามลําดับ —บทเรียนแต่ละบทจะสร้างขึ้นบนตัวเชื่อมต่อที่สร้างขึ้นในบทเรียนที่แล้ว โดยการเพิ่มความสามารถใหม่ให้กับตัวเชื่อมต่อของคุณแบบเพิ่มหน่วย
ในบทเรียนนี้ คุณจะ:
- เพิ่มการสนับสนุนการแบ่งหน้าไปยังตัวเชื่อมต่อ
Rest API จํานวนมากส่งกลับข้อมูลใน "หน้า" ที่จําเป็นต้องมีไคลเอ็นต์เพื่อทําการร้องขอหลายรายการเพื่อใส่ผลลัพธ์เข้าด้วยกัน แม้ว่าจะมีหลักทั่วไปบางอย่างสําหรับการแบ่งหน้า (เช่น RFC 5988) โดยทั่วไปแล้วจะแตกต่างกันจาก API เป็น API โชคดีที่ TripPin เป็นบริการ OData และ มาตรฐาน OData กําหนดวิธีการแบ่งหน้าโดยใช้ ค่า odata.nextLink ที่ส่งกลับในเนื้อความของการตอบสนอง
เพื่อทําให้การเกิดซ้ําก่อนหน้านี้ของตัวเชื่อมต่อTripPin.Feed
ง่ายขึ้น ฟังก์ชันนี้ไม่ทราบหน้า เพียงแค่แยกวิเคราะห์สิ่งที่ JSON ถูกส่งกลับจากคําขอและจัดรูปแบบเป็นตาราง ผู้ที่คุ้นเคยกับโปรโตคอล OData อาจสังเกตเห็นว่าสมมติฐานที่ไม่ถูกต้องจํานวนมากเกิดขึ้นในรูปแบบ การตอบสนอง (เช่นสมมติว่ามีเขตข้อมูลที่มี value
อาร์เรย์ของระเบียน)
ในบทเรียนนี้ คุณปรับปรุงตรรกะการจัดการการตอบกลับของคุณ โดยการทําให้ทราบหน้า บทช่วยสอนในอนาคตทําให้หน้าการจัดการตรรกะมีประสิทธิภาพมากขึ้นและสามารถจัดการรูปแบบการตอบสนองหลายรายการ (รวมถึงข้อผิดพลาดจากบริการ)
หมายเหตุ
คุณไม่จําเป็นต้องใช้ตรรกะการแบ่งหน้าของคุณเองด้วยตัวเชื่อมต่อที่ ยึดตาม OData.Feed เนื่องจากจะจัดการกับทั้งหมดให้คุณโดยอัตโนมัติ
รายการตรวจสอบการแบ่งหน้า
เมื่อมีการใช้การสนับสนุนการแบ่งหน้า คุณจะต้องทราบสิ่งต่อไปนี้เกี่ยวกับ API ของคุณ:
- คุณจะร้องขอหน้าถัดไปของข้อมูลได้อย่างไร
- กลไกการแบ่งหน้าเกี่ยวข้องกับการคํานวณค่าหรือคุณแยก URL สําหรับหน้าถัดไปออกจากการตอบสนองหรือไม่
- คุณจะรู้ได้ไงว่าจะหยุดการแบ่งหน้าเมื่อใด
- มีพารามิเตอร์ที่เกี่ยวข้องกับการแบ่งหน้าที่คุณควรระวังหรือไม่ (เช่น "ขนาดหน้า")
คําตอบสําหรับคําถามเหล่านี้ส่งผลกระทบต่อวิธีที่คุณใช้ตรรกะการแบ่งหน้าของคุณ ในขณะที่มีการใช้โค้ดซ้ําในการใช้งานการแบ่งหน้า (เช่น การใช้ Table.GenerateByPage แต่ตัวเชื่อมต่อส่วนใหญ่จะต้องใช้ตรรกะแบบกําหนดเอง
หมายเหตุ
บทเรียนนี้ประกอบด้วยตรรกะการแบ่งหน้าสําหรับบริการ OData ซึ่งตามรูปแบบเฉพาะ ตรวจสอบเอกสารประกอบสําหรับ API ของคุณเพื่อกําหนดการเปลี่ยนแปลงที่คุณจะต้องทําในตัวเชื่อมต่อของคุณเพื่อสนับสนุนรูปแบบการแบ่งหน้า
ภาพรวมของการแบ่งหน้า OData
การแบ่งหน้า OData ถูกขับเคลื่อนด้วย คําอธิบายประกอบ nextLink ที่อยู่ภายในส่วนข้อมูลการตอบสนอง ค่า nextLink ประกอบด้วย URL ไปยังหน้าถัดไปของข้อมูล คุณจะทราบว่ามีหน้าอื่นของข้อมูล โดยการค้นหา odata.nextLink
เขตข้อมูลในวัตถุด้านนอกสุดในการตอบสนอง ถ้าไม่มี odata.nextLink
เขตข้อมูล คุณได้อ่านข้อมูลของคุณทั้งหมดแล้ว
{
"odata.context": "...",
"odata.count": 37,
"value": [
{ },
{ },
{ }
],
"odata.nextLink": "...?$skiptoken=342r89"
}
บริการ OData บางอย่างอนุญาตให้ไคลเอ็นต์ใส่ การกําหนดลักษณะขนาดหน้าสูงสุด แต่ขึ้นอยู่กับบริการว่าจะให้บริการหรือไม่เคารพหรือไม่ Power Query ควรสามารถจัดการการตอบกลับทุกขนาด ดังนั้นคุณไม่ต้องกังวลเกี่ยวกับการระบุการกําหนดลักษณะขนาดหน้า — คุณสามารถสนับสนุนสิ่งใดก็ตามที่บริการนั้นขว้างมาให้คุณ
ข้อมูลเพิ่มเติมเกี่ยวกับ เพจจิ้ง ที่ขับเคลื่อนด้วยเซิร์ฟเวอร์สามารถพบได้ในข้อมูลจําเพาะของ OData
การทดสอบ TripPin
ก่อนที่จะแก้ไขการใช้งานการแบ่งหน้าของคุณ ให้ยืนยันลักษณะการทํางานปัจจุบันของส่วนขยายจาก บทช่วยสอนก่อนหน้า คิวรีทดสอบต่อไปนี้จะเรียกใช้ตาราง บุคคล และเพิ่มคอลัมน์ดัชนีเพื่อแสดงจํานวนแถวปัจจุบันของคุณ
let
source = TripPin.Contents(),
data = source{[Name="People"]}[Data],
withRowCount = Table.AddIndexColumn(data, "Index")
in
withRowCount
เปิดใช้งาน Fiddler และเรียกใช้คิวรีใน Power Query SDK โปรดทราบว่าคิวรีจะส่งกลับตารางที่มีแปดแถว (ดัชนี 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
ในตอนนี้คุณกําลังทําการเปลี่ยนแปลงต่อไปนี้กับส่วนขยายของคุณ:
- นําเข้าฟังก์ชันทั่วไป
Table.GenerateByPage
GetAllPagesByNextLink
เพิ่มฟังก์ชันที่ใช้Table.GenerateByPage
กาวหน้าทั้งหมดเข้าด้วยกันGetPage
เพิ่มฟังก์ชันที่สามารถอ่านหน้าข้อมูลเดียวได้GetNextLink
เพิ่มฟังก์ชันเพื่อแยก URL ถัดไปจากคําตอบ- อัปเดต
TripPin.Feed
เพื่อใช้ฟังก์ชันตัวอ่านหน้าใหม่
หมายเหตุ
ตามที่ระบุไว้ก่อนหน้านี้ในบทช่วยสอน นี้ ตรรกะการแบ่งหน้าจะแตกต่างกันระหว่างแหล่งข้อมูล การดําเนินการที่นี่พยายามแบ่งตรรกะออกเป็นฟังก์ชันที่ควรนํามาใช้ใหม่สําหรับแหล่งข้อมูลที่ใช้ ลิงก์ ถัดไปที่ส่งกลับในการตอบสนอง
Table.GenerateByPage
เมื่อต้องรวมหลายหน้า (อาจเป็น) หลายหน้าที่ส่งกลับโดยแหล่งข้อมูลลงในตารางเดียว เราจะใช้Table.GenerateByPage
ฟังก์ชันนี้ใช้เป็นอาร์กิวเมนต์สําหรับ getNextPage
ฟังก์ชันที่ควรทําตามที่ชื่อแนะนํา: ดึงข้อมูลหน้าถัดไป Table.GenerateByPage
จะเรียกใช้ getNextPage
ฟังก์ชันซ้ํา ๆ แต่ละครั้งที่ส่งผ่านผลลัพธ์ที่สร้างขึ้นในครั้งสุดท้ายที่ถูกเรียกจนกว่าจะกลับไป null
ส่งสัญญาณกลับว่าไม่มีหน้าที่พร้อมใช้งานอีก
เนื่องจากฟังก์ชันนี้ไม่ใช่ส่วนหนึ่งของไลบรารีมาตรฐานของ Power Query คุณจะต้องคัดลอกรหัสต้นทางลงในไฟล์ .pq ของคุณ
การใช้ GetAllPagesByNextLink
เนื้อความของฟังก์ชันของคุณ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
ฟังก์ชันของคุณ GetNextLink
เพียงแค่ตรวจสอบเนื้อความของการตอบกลับสําหรับ @odata.nextLink
เขตข้อมูล และส่งกลับค่า
// In this implementation, 'response' will be 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 แถวในการตอบกลับแทนที่จะเป็นแปดแถว
ถ้าคุณดูคําขอใน fiddler ตอนนี้คุณควรเห็นคําขอแยกต่างหากสําหรับแต่ละหน้าของข้อมูล
หมายเหตุ
คุณจะสังเกตเห็นคําขอซ้ําสําหรับหน้าแรกของข้อมูลจากบริการ ซึ่งไม่เหมาะสม คําขอเพิ่มเติมคือผลลัพธ์ของลักษณะการทํางานของการตรวจสอบ Schema ของกลไกจัดการ M ละเว้นปัญหานี้ในตอนนี้และแก้ไขปัญหาใน บทช่วยสอนถัดไป ซึ่งคุณจะใช้ Schema ที่ชัดเจน
บทสรุป
บทเรียนนี้แสดงวิธีใช้การสนับสนุนการแบ่งหน้าสําหรับ Rest API ในขณะที่ตรรกะอาจแตกต่างกันระหว่าง API แต่รูปแบบที่กําหนดไว้ที่นี่ควรนํามาใช้ใหม่ด้วยการปรับเปลี่ยนเล็กน้อย
ในบทเรียนถัดไป คุณจะได้ดูวิธีการใช้ Schema ที่ชัดเจนกับข้อมูลของคุณ ซึ่งนอกเหนือจากชนิดข้อมูลและnumber
รูปแบบธรรมดาtext
ที่คุณได้รับจากJson.Document