หมายเหตุ
การเข้าถึงหน้านี้ต้องได้รับการอนุญาต คุณสามารถลอง ลงชื่อเข้าใช้หรือเปลี่ยนไดเรกทอรีได้
การเข้าถึงหน้านี้ต้องได้รับการอนุญาต คุณสามารถลองเปลี่ยนไดเรกทอรีได้
บทช่วยสอนแบบหลายส่วนนี้ครอบคลุมการสร้างส่วนขยายแหล่งข้อมูลใหม่สําหรับ Power Query บทช่วยสอนมีไว้ให้ทําตามลําดับ—แต่ละบทเรียนจะสร้างขึ้นจากตัวเชื่อมต่อที่สร้างขึ้นในบทเรียนก่อนหน้า โดยจะเพิ่มความสามารถใหม่ให้กับตัวเชื่อมต่อของคุณทีละน้อย
ในบทเรียนนี้ คุณ:
- สร้างฟังก์ชันพื้นฐานที่เรียก REST API โดยใช้ Web.Contents
- ดูวิธีตั้งค่าส่วนหัวของคําขอและประมวลผลการตอบกลับ JSON
- ใช้ Power BI Desktop เพื่อจัดเรียงการตอบกลับในรูปแบบที่เป็นมิตรกับผู้ใช้
บทเรียนนี้จะแปลงตัวเชื่อมต่อที่ใช้ OData สําหรับ บริการ TripPin (ที่สร้างขึ้นใน บทเรียนก่อนหน้า) เป็นตัวเชื่อมต่อที่คล้ายกับสิ่งที่คุณจะสร้างสําหรับ RESTful API ใดๆ OData เป็น RESTful API แต่มีชุดข้อตกลงคงที่ ข้อดีของ OData คือมีสคีมา โปรโตคอลการดึงข้อมูล และภาษาคิวรีมาตรฐาน การเลิกใช้ OData.Feed จําเป็นต้องสร้างความสามารถเหล่านี้ลงในตัวเชื่อมต่อด้วยตัวคุณเอง
สรุปของขั้วต่อ 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 ควรแสดงค่า เรกคอร์ด สําหรับซิงเกิลตัน Me
หากคุณเปรียบเทียบฟิลด์ในหน้าต่างเอาต์พุตกับฟิลด์ที่ส่งคืนในการตอบกลับ 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.FeedWeb.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%! ตอนนี้คุณสูญเสียข้อมูลประเภทและสคีมาทั้งหมด แต่ยังไม่จําเป็นต้องมุ่งเน้นไปที่ส่วนนั้น
อัปเดตคิวรีของคุณเพื่อเข้าถึงเอนทิตี/ตาราง TripPin บางรายการ เช่น:
https://services.odata.org/v4/TripPinService/Airlineshttps://services.odata.org/v4/TripPinService/Airportshttps://services.odata.org/v4/TripPinService/Me/Trips
คุณสังเกตเห็นว่าเส้นทางที่เคยส่งกลับตารางที่มีการจัดรูปแบบสวยงามตอนนี้ส่งคืนเขตข้อมูล "ค่า" ระดับบนสุดที่มี [รายการ] ฝังตัว คุณต้องทําการแปลงบางอย่างกับผลลัพธ์เพื่อให้สามารถใช้งานได้สําหรับสถานการณ์การใช้ของผู้ใช้ปลายทาง
การเขียนการแปลงใน Power Query
แม้ว่าจะเป็นไปได้ที่จะเขียนการแปลง M ของคุณด้วยมือ แต่คนส่วนใหญ่ชอบใช้ Power Query เพื่อจัดรูปร่างข้อมูลของตน คุณเปิดส่วนขยายของคุณใน Power BI Desktop และใช้เพื่อออกแบบคิวรีเพื่อเปลี่ยนผลลัพธ์ให้เป็นรูปแบบที่เป็นมิตรกับผู้ใช้มากขึ้น สร้างโซลูชันของคุณใหม่ คัดลอกไฟล์ส่วนขยายใหม่ไปยังไดเรกทอรีตัวเชื่อมต่อข้อมูลแบบกําหนดเองของคุณ และเปิดใช้ 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
ตั้งชื่อแบบสอบถาม ("สายการบิน")
สร้างแบบสอบถามเปล่าใหม่ คราวนี้ ให้ใช้ฟังก์ชันเพื่อ 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 และเลือกปุ่ม รีเฟรชตัวอย่าง ในตัวแก้ไข Power Query ให้จดบันทึกคําขอเว็บแยกต่างหากสําหรับแต่ละรายการในตารางการนําทางของคุณ คําขอแยกต่างหากเหล่านี้บ่งชี้ว่ามีการประเมินอย่างกระตือรือร้น ซึ่งไม่เหมาะอย่างยิ่งเมื่อสร้างตารางการนําทางที่มีองค์ประกอบจํานวนมาก บทเรียนต่อๆ ไปจะแสดงวิธีสร้างตารางการนําทางที่เหมาะสมซึ่งรองรับการประเมินแบบขี้เกียจ
บทสรุป
บทเรียนนี้แสดงวิธีสร้างตัวเชื่อมต่ออย่างง่ายสําหรับบริการ REST ในกรณีนี้ คุณเปลี่ยนส่วนขยาย OData ที่มีอยู่ให้เป็นส่วนขยาย REST มาตรฐาน (โดยใช้ Web.Contents) แต่แนวคิดเดียวกันนี้ใช้ได้หากคุณกําลังสร้างส่วนขยายใหม่ตั้งแต่เริ่มต้น
ในบทเรียนถัดไป คุณจะใช้คิวรีที่สร้างขึ้นในบทเรียนนี้โดยใช้ Power BI Desktop และเปลี่ยนเป็นตารางการนําทางที่แท้จริงภายในส่วนขยาย