TripPin ส่วนที่ 2 - ตัวเชื่อมต่อข้อมูลสําหรับบริการ REST
บทช่วยสอนแบบหลายส่วนนี้ครอบคลุมการสร้างส่วนขยายแหล่งข้อมูลใหม่สําหรับ Power Query บทช่วยสอนมีไว้ให้ทําตามลําดับ —บทเรียนแต่ละบทจะสร้างขึ้นบนตัวเชื่อมต่อที่สร้างขึ้นในบทเรียนที่แล้ว โดยการเพิ่มความสามารถใหม่ให้กับตัวเชื่อมต่อของคุณแบบเพิ่มหน่วย
ในบทเรียนนี้ คุณจะ:
- สร้างฟังก์ชันพื้นฐานที่เรียกใช้ REST API โดยใช้ Web.Contents
- เรียนรู้วิธีการตั้งค่าส่วนหัวของคําขอและประมวลผลการตอบกลับ JSON
- ใช้ Power BI Desktop เพื่อจัดรูปการตอบกลับเป็นรูปแบบที่ใช้งานง่าย
บทเรียนนี้แปลงตัวเชื่อมต่อตาม OData สําหรับ บริการ TripPin (สร้างขึ้นใน บทเรียนก่อนหน้า) เป็นตัวเชื่อมต่อที่คล้ายกับบางสิ่งที่คุณสร้างขึ้นสําหรับ RESTful API ใด ๆ OData เป็น API RESTful แต่หนึ่งด้วยชุดแบบแผนทั่วไป ประโยชน์ของ OData คือมี Schema โพรโทคอลการเรียกข้อมูล และภาษาคิวรีมาตรฐาน การแย่งใช้งาน OData.Feed จะต้องให้เราสร้างความสามารถเหล่านี้ลงในตัวเชื่อมต่อด้วยตนเอง
การสรุปของตัวเชื่อมต่อ OData
ก่อนที่คุณจะลบฟังก์ชัน OData ออกจากตัวเชื่อมต่อของคุณ เรามาทําการทบทวนอย่างคร่าว ๆ เกี่ยวกับสิ่งที่ OData ทําในขณะนี้ (ส่วนใหญ่อยู่เบื้องหลัง) เพื่อดึงข้อมูลจากบริการ
เปิดโครงการส่วนขยาย TripPin จาก ส่วนที่ 1 ใน Visual Studio Code เปิดไฟล์คิวรีและวางในคิวรีต่อไปนี้:
TripPin.Feed("https://services.odata.org/v4/TripPinService/Me")
เปิด Fiddler แล้วประเมินไฟล์ Power Query ปัจจุบันใน Visual Studio Code
ใน Fiddler มีการร้องขอสามรายการไปยังเซิร์ฟเวอร์:
/Me
—URL จริงที่คุณร้องขอ/$metadata
—การเรียกใช้โดยอัตโนมัติโดยOData.Feed
ฟังก์ชันเพื่อกําหนด schema และพิมพ์ข้อมูลเกี่ยวกับการตอบสนอง/Me/BestFriend
—หนึ่งในเขตข้อมูลที่ถูกดึงมา (กระตือรือร้น) เมื่อคุณแสดงรายการ /Me singleton ในกรณีนี้ การเรียกใช้จะส่งผลให้เกิด204 No Content
สถานะ
การประเมิน M ส่วนใหญ่ขี้เกียจ ในกรณีส่วนใหญ่ ค่าข้อมูลจะถูกดึง/ดึงเมื่อจําเป็นเท่านั้น มีสถานการณ์ต่าง ๆ (เช่น /Me/BestFriend) ที่ดึงค่าอย่างกระตือรือร้น ซึ่งมีแนวโน้มที่จะเกิดขึ้นเมื่อข้อมูลชนิดเป็นสิ่งจําเป็นสําหรับสมาชิก และกลไกจัดการไม่มีวิธีอื่นในการกําหนดชนิดมากกว่าที่จะดึงค่าและตรวจสอบ การทําสิ่งที่ขี้เกียจ (นั่นคือการหลีกเลี่ยงการดึงเบื้องหน้า) เป็นหนึ่งในประเด็นสําคัญที่ทําให้ตัวเชื่อมต่อ M ทํางานได้
โปรดสังเกตส่วนหัวของคําขอที่ถูกส่งพร้อมกับคําขอและรูปแบบ JSON ของการตอบสนองของคําขอ /Me
{
"@odata.context": "https://services.odata.org/v4/TripPinService/$metadata#Me",
"UserName": "aprilcline",
"FirstName": "April",
"LastName": "Cline",
"MiddleName": null,
"Gender": "Female",
"Age": null,
"Emails": [ "April@example.com", "April@contoso.com" ],
"FavoriteFeature": "Feature1",
"Features": [ ],
"AddressInfo": [
{
"Address": "P.O. Box 555",
"City": {
"Name": "Lander",
"CountryRegion": "United States",
"Region": "WY"
}
}
],
"HomeAddress": null
}
เมื่อการประเมินคิวรีเสร็จสิ้น หน้าต่างผลลัพธ์ PQTest ควรแสดงค่า เรกคอร์ด สําหรับเมลตัน
ถ้าคุณเปรียบเทียบเขตข้อมูลในหน้าต่างเอาต์พุตกับเขตข้อมูลที่ส่งกลับในการตอบสนอง JSON ดิบ คุณจะสังเกตเห็นว่าไม่ตรงกัน ผลลัพธ์ของคิวรีมีเขตข้อมูลอื่น ๆ (Friends
, , Trips
, GetFriendsTrips
) ที่ไม่ปรากฏที่ใดเลยในการตอบสนอง JSON ฟังก์ชัน OData.Feed จะผนวกเขตข้อมูลเหล่านี้เข้ากับระเบียนโดยยึดตาม schema ที่ส่งกลับโดย$metadata โดยอัตโนมัติ นี่คือตัวอย่างที่ดีของวิธีการที่ตัวเชื่อมต่ออาจเสริม และ/หรือจัดรูปแบบการตอบสนองจากบริการใหม่เพื่อให้ประสบการณ์ใช้งานของผู้ใช้ดียิ่งขึ้น
การสร้างตัวเชื่อมต่อ REST พื้นฐาน
ตอนนี้คุณจะเพิ่มฟังก์ชันที่ส่งออกใหม่ไปยังตัวเชื่อมต่อของคุณที่เรียกใช้ Web.Contents
เพื่อให้สามารถทําการร้องขอเว็บที่สําเร็จไปยังบริการ OData อย่างไรก็ตามคุณจะต้องตั้งค่าส่วนหัว OData มาตรฐานบางอย่าง คุณสามารถทําได้โดยการกําหนดชุดส่วนหัวทั่วไปเป็นตัวแปรใหม่ในตัวเชื่อมต่อของคุณ:
DefaultRequestHeaders = [
#"Accept" = "application/json;odata.metadata=minimal", // column name and values only
#"OData-MaxVersion" = "4.0" // we only support v4
];
คุณเปลี่ยนการใช้งานฟังก์ชันของคุณTripPin.Feed
เพื่อให้แทนที่จะใช้ OData.Feed
Web.Contents เพื่อสร้างการร้องขอเว็บ และแยกวิเคราะห์ผลลัพธ์เป็นเอกสาร JSON
TripPinImpl = (url as text) =>
let
source = Web.Contents(url, [ Headers = DefaultRequestHeaders ]),
json = Json.Document(source)
in
json;
อย่าลืมสร้างตัวเชื่อมต่อของคุณหลังจากที่คุณได้ทําการเปลี่ยนแปลงไฟล์ตัวเชื่อมต่อ จากนั้นคุณสามารถประเมินไฟล์คิวรี (TripPin.query.pq) ขณะนี้ผลลัพธ์ของระเบียน /Me มีลักษณะคล้ายกับ JSON ดิบที่คุณเห็นในคําขอ Fiddler
หากคุณดู Fiddler เมื่อเรียกใช้ฟังก์ชันใหม่ คุณจะสังเกตเห็นว่าขณะนี้การประเมินสร้างคําขอเว็บเดียวแทนที่จะเป็นสาม ขอแสดงความยินดี - คุณมีประสิทธิภาพการทํางานเพิ่มขึ้น 300%! ตอนนี้คุณได้สูญเสียข้อมูลชนิดและ schema ทั้งหมดแล้ว แต่ยังไม่จําเป็นต้องมุ่งเน้นไปที่ส่วนนั้น
อัปเดตคิวรีของคุณเพื่อเข้าถึงเอนทิตี/ตาราง TripPin บางอย่าง เช่น:
https://services.odata.org/v4/TripPinService/Airlines
https://services.odata.org/v4/TripPinService/Airports
https://services.odata.org/v4/TripPinService/Me/Trips
คุณจะสังเกตเห็นว่าเส้นทางที่ใช้ในการส่งกลับตารางที่จัดรูปแบบอย่างดีในขณะนี้ส่งกลับเขตข้อมูล "ค่า" ระดับบนสุดที่มี [รายการ] แบบฝังตัว คุณจะต้องทําการแปลงข้อมูลบางอย่างบนผลลัพธ์เพื่อให้สามารถใช้ได้สําหรับสถานการณ์ปริมาณการใช้ของผู้ใช้ปลายทาง
การเขียนการแปลงใน Power Query
ถึงแม้ว่าคุณจะสามารถสร้างการแปลง M ของคุณด้วยมือ แต่คนส่วนใหญ่ต้องการใช้ Power Query เพื่อจัดรูปร่างข้อมูลของพวกเขา คุณจะเปิดส่วนขยายของคุณใน Power BI Desktop และใช้เพื่อออกแบบคิวรีเพื่อเปลี่ยนเอาต์พุตให้อยู่ในรูปแบบที่เป็นมิตรกับผู้ใช้มากขึ้น สร้างโซลูชันของคุณใหม่ คัดลอกไฟล์ส่วนขยายใหม่ไปยังไดเรกทอรี custom Data เชื่อมต่อ ors ของคุณ และเปิด Power BI Desktop อีกครั้ง
เริ่มคิวรี่ว่างเปล่าใหม่ และวางรายการต่อไปนี้ลงในแถบสูตร:
= TripPin.Feed("https://services.odata.org/v4/TripPinService/Airlines")
ตรวจสอบให้แน่ใจว่ามีเครื่องหมาย =
จัดการเอาต์พุตจนกว่าจะมีลักษณะเหมือนตัวดึงข้อมูล OData ต้นฉบับ ซึ่งเป็นตารางที่มีสองคอลัมน์: AirlineCode และ Name
คิวรีที่เป็นผลลัพธ์ควรมีลักษณะดังนี้:
let
Source = TripPin.Feed("https://services.odata.org/v4/TripPinService/Airlines"),
value = Source[value],
toTable = Table.FromList(value, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
expand = Table.ExpandRecordColumn(toTable, "Column1", {"AirlineCode", "Name"}, {"AirlineCode", "Name"})
in
expand
ตั้งชื่อคิวรี ("Airlines")
สร้างคิวรี่ว่างเปล่าใหม่ ในครั้งนี้ ให้ใช้ TripPin.Feed
ฟังก์ชันเพื่อเข้าถึงเอนทิตี /Airports นําการแปลงไปใช้จนกว่าคุณจะได้สิ่งที่คล้ายกับการแชร์ที่แสดงด้านล่าง นอกจากนี้ยังสามารถค้นหาคิวรีที่ตรงกันได้ที่ด้านล่าง — ตั้งชื่อคิวรีนี้ ("สนามบิน") เช่นกัน
let
Source = TripPin.Feed("https://services.odata.org/v4/TripPinService/Airports"),
value = Source[value],
#"Converted to Table" = Table.FromList(value, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
#"Expanded Column1" = Table.ExpandRecordColumn(#"Converted to Table", "Column1", {"Name", "IcaoCode", "IataCode", "Location"}, {"Name", "IcaoCode", "IataCode", "Location"}),
#"Expanded Location" = Table.ExpandRecordColumn(#"Expanded Column1", "Location", {"Address", "Loc", "City"}, {"Address", "Loc", "City"}),
#"Expanded City" = Table.ExpandRecordColumn(#"Expanded Location", "City", {"Name", "CountryRegion", "Region"}, {"Name.1", "CountryRegion", "Region"}),
#"Renamed Columns" = Table.RenameColumns(#"Expanded City",{{"Name.1", "City"}}),
#"Expanded Loc" = Table.ExpandRecordColumn(#"Renamed Columns", "Loc", {"coordinates"}, {"coordinates"}),
#"Added Custom" = Table.AddColumn(#"Expanded Loc", "Latitude", each [coordinates]{1}),
#"Added Custom1" = Table.AddColumn(#"Added Custom", "Longitude", each [coordinates]{0}),
#"Removed Columns" = Table.RemoveColumns(#"Added Custom1",{"coordinates"}),
#"Changed Type" = Table.TransformColumnTypes(#"Removed Columns",{{"Name", type text}, {"IcaoCode", type text}, {"IataCode", type text}, {"Address", type text}, {"City", type text}, {"CountryRegion", type text}, {"Region", type text}, {"Latitude", type number}, {"Longitude", type number}})
in
#"Changed Type"
คุณสามารถทําซ้ํากระบวนการนี้สําหรับเส้นทางเพิ่มเติมภายใต้บริการ เมื่อคุณพร้อมแล้ว ย้ายไปยังขั้นตอนถัดไปของการสร้างตารางนําทาง (จําลอง)
การจําลองตารางนําทาง
ในตอนนี้ คุณกําลังจะสร้างตาราง (โดยใช้รหัส M) ที่แสดงเอนทิตี TripPin ที่ได้รับการจัดรูปแบบอย่างดีของคุณ
เริ่มคิวรี่ว่างเปล่าใหม่และแสดงเครื่องมือแก้ไขขั้นสูง
วางในคิวรีต่อไปนี้:
let
source = #table({"Name", "Data"}, {
{ "Airlines", Airlines },
{ "Airports", Airports }
})
in
source
ถ้าคุณไม่ได้ตั้งค่าระดับความเป็นส่วนตัวของคุณเป็น "ละเว้นการตั้งค่าระดับความเป็นส่วนตัวเสมอ" (หรือที่เรียกว่า "การรวมด่วน") คุณจะเห็นพร้อมท์ความเป็นส่วนตัว
พร้อมท์ความเป็นส่วนตัวปรากฏขึ้นเมื่อคุณกําลังรวมข้อมูลจากหลายแหล่งข้อมูล และยังไม่ได้ระบุระดับความเป็นส่วนตัวสําหรับแหล่งข้อมูลหนึ่งหรือหลายแหล่ง เลือกปุ่ม ดําเนินการต่อ และตั้งค่าระดับความเป็นส่วนตัวของแหล่งข้อมูลด้านบนเป็นสาธารณะ
เลือก บันทึก และตารางของคุณจะปรากฏขึ้น แม้ว่านี่จะยังไม่ใช่ตารางการนําทาง แต่ก็มีฟังก์ชันพื้นฐานที่คุณจําเป็นต้องเปลี่ยนเป็นหนึ่งในบทเรียนที่ตามมา
การตรวจสอบชุดข้อมูลจะไม่เกิดขึ้นเมื่อเข้าถึงแหล่งข้อมูลหลายแหล่งจากภายในส่วนขยาย เนื่องจากการเรียกใช้แหล่งข้อมูลทั้งหมดที่เกิดขึ้นจากภายในส่วนขยายจะสืบทอดบริบทการรับรองความถูกต้องเดียวกัน จึงสันนิษฐานว่าการเรียกนั้นเป็น "ปลอดภัย" ที่จะรวมกัน ส่วนขยายของคุณจะถือว่าเป็นแหล่งข้อมูลเดียวเสมอเมื่อถึงกฎการรวมข้อมูล ผู้ใช้จะยังคงได้รับพร้อมท์ความเป็นส่วนตัวปกติเมื่อรวมแหล่งข้อมูลของคุณกับแหล่งข้อมูล M อื่น ๆ
ถ้าคุณเรียกใช้ Fiddler และเลือกปุ่ม รีเฟรชตัวอย่าง ในตัวแก้ไขคิวรี ให้สังเกตการร้องขอเว็บที่แยกต่างหากสําหรับแต่ละรายการในตารางการนําทางของคุณ ซึ่งแสดงว่าการประเมินผลกระหายเกิดขึ้น ซึ่งไม่เหมาะสมเมื่อสร้างตารางการนําทางที่มีองค์ประกอบจํานวนมาก บทเรียนที่ตามมาแสดงวิธีการสร้างตารางนําทางที่เหมาะสมที่สนับสนุนการประเมินผลขี้เกียจ
บทสรุป
บทเรียนนี้แสดงวิธีการสร้างตัวเชื่อมต่ออย่างง่ายสําหรับบริการ REST ในกรณีนี้ คุณได้เปลี่ยนส่วนขยาย OData ที่มีอยู่เป็นส่วนขยาย REST มาตรฐาน (โดยใช้ Web.Contents) แต่แนวคิดเดียวกันจะนําไปใช้ถ้าคุณกําลังสร้างส่วนขยายใหม่ตั้งแต่เริ่มต้น
ในบทเรียนถัดไป คุณจะได้ใช้คิวรีที่สร้างขึ้นในบทเรียนนี้โดยใช้ Power BI Desktop และเปลี่ยนคิวรีเหล่านั้นให้เป็นตารางการนําทางที่แท้จริงภายในส่วนขยาย