TripPin bagian 5 - Halaman
Tutorial multi-bagian ini mencakup pembuatan ekstensi sumber data baru untuk Power Query. Tutorial ini dimaksudkan untuk dilakukan secara berurutan—setiap pelajaran dibangun pada konektor yang dibuat dalam pelajaran sebelumnya, secara bertahap menambahkan kemampuan baru ke konektor Anda.
Dalam pelajaran ini, Anda akan:
- Menambahkan dukungan halaman ke konektor
Banyak REST API mengembalikan data di "halaman", mengharuskan klien membuat beberapa permintaan untuk menyatukan hasilnya. Meskipun ada beberapa konvensi umum untuk paginasi (seperti RFC 5988), umumnya bervariasi dari API ke API. Untungnya, TripPin adalah layanan OData, dan standar OData mendefinisikan cara melakukan penomoran halaman menggunakan nilai odata.nextLink yang dikembalikan dalam isi respons.
Untuk menyederhanakan iterasi konektor sebelumnya, TripPin.Feed
fungsi tidak diketahui halaman. Ini hanya mengurai JSON apa pun yang dikembalikan dari permintaan dan memformatnya sebagai tabel. Mereka yang terbiasa dengan protokol OData mungkin telah memperhatikan bahwa banyak asumsi yang salah dibuat pada format respons (seperti dengan asumsi ada bidang yang value
berisi array rekaman).
Dalam pelajaran ini, Anda meningkatkan logika penanganan respons Anda dengan membuatnya sadar halaman. Tutorial di masa mendatang membuat logika penanganan halaman lebih kuat dan dapat menangani beberapa format respons (termasuk kesalahan dari layanan).
Catatan
Anda tidak perlu menerapkan logika halaman Anda sendiri dengan konektor berdasarkan OData.Feed, karena menangani semuanya untuk Anda secara otomatis.
Daftar periksa halaman
Saat menerapkan dukungan paging, Anda harus mengetahui hal-hal berikut tentang API Anda:
- Bagaimana Anda meminta halaman data berikutnya?
- Apakah mekanisme penomor melibatkan perhitungan nilai, atau apakah Anda mengekstrak URL untuk halaman berikutnya dari respons?
- Bagaimana Anda tahu kapan harus berhenti penomor?
- Apakah ada parameter yang terkait dengan penomoran halaman yang harus Anda waspadai? (seperti "ukuran halaman")
Jawaban atas pertanyaan-pertanyaan ini berdampak pada cara Anda menerapkan logika halaman Anda. Meskipun ada beberapa jumlah penggunaan kembali kode di seluruh implementasi penomoran halaman (seperti penggunaan Table.GenerateByPage, sebagian besar konektor akan akhirnya memerlukan logika kustom.
Catatan
Pelajaran ini berisi logika halaman untuk layanan OData, yang mengikuti format tertentu. Periksa dokumentasi API Anda untuk menentukan perubahan yang perlu Anda buat di konektor Anda untuk mendukung format halamannya.
Gambaran umum OData Paging
Penomor OData didorong oleh anotasi nextLink yang terkandung dalam payload respons. Nilai nextLink berisi URL ke halaman data berikutnya. Anda akan tahu apakah ada halaman data lain dengan mencari odata.nextLink
bidang di objek terluar dalam respons. Jika tidak odata.nextLink
ada bidang, Anda telah membaca semua data Anda.
{
"odata.context": "...",
"odata.count": 37,
"value": [
{ },
{ },
{ }
],
"odata.nextLink": "...?$skiptoken=342r89"
}
Beberapa layanan OData memungkinkan klien untuk menyediakan preferensi ukuran halaman maks, tetapi terserah layanan apakah akan menghormatinya atau tidak. Power Query harus dapat menangani respons dengan ukuran apa pun, sehingga Anda tidak perlu khawatir menentukan preferensi ukuran halaman—Anda dapat mendukung apa pun yang dilemparkan layanan kepada Anda.
Informasi selengkapnya tentang Halaman Berbasis Server dapat ditemukan dalam spesifikasi OData.
Menguji TripPin
Sebelum memperbaiki implementasi halaman Anda, konfirmasikan perilaku ekstensi saat ini dari tutorial sebelumnya. Kueri pengujian berikut mengambil tabel Orang dan menambahkan kolom indeks untuk memperlihatkan jumlah baris Anda saat ini.
let
source = TripPin.Contents(),
data = source{[Name="People"]}[Data],
withRowCount = Table.AddIndexColumn(data, "Index")
in
withRowCount
Aktifkan Fiddler, dan jalankan kueri di Power Query SDK. Perhatikan bahwa kueri mengembalikan tabel dengan delapan baris (indeks 0 hingga 7).
Jika Anda melihat isi respons dari fiddler, Anda akan melihat bahwa itu sebenarnya berisi @odata.nextLink
bidang, menunjukkan bahwa ada lebih banyak halaman data yang tersedia.
{
"@odata.context": "https://services.odata.org/V4/TripPinService/$metadata#People",
"@odata.nextLink": "https://services.odata.org/v4/TripPinService/People?%24skiptoken=8",
"value": [
{ },
{ },
{ }
]
}
Menerapkan halaman untuk TripPin
Anda sekarang akan membuat perubahan berikut pada ekstensi Anda:
- Mengimpor fungsi umum
Table.GenerateByPage
GetAllPagesByNextLink
Menambahkan fungsi yang menggunakanTable.GenerateByPage
untuk merekatkan semua halaman bersama-samaGetPage
Menambahkan fungsi yang dapat membaca satu halaman dataGetNextLink
Menambahkan fungsi untuk mengekstrak URL berikutnya dari respons- Perbarui
TripPin.Feed
untuk menggunakan fungsi pembaca halaman baru
Catatan
Seperti yang dinyatakan sebelumnya dalam tutorial ini, logika halaman akan bervariasi di antara sumber data. Implementasi di sini mencoba memecah logika menjadi fungsi yang harus dapat digunakan kembali untuk sumber yang menggunakan tautan berikutnya yang dikembalikan dalam respons.
Table.GenerateByPage
Untuk menggabungkan beberapa halaman (berpotensi) yang dikembalikan oleh sumber ke dalam satu tabel, kita akan menggunakan Table.GenerateByPage
. Fungsi ini mengambil sebagai argumennya fungsi getNextPage
yang harus melakukan apa yang namanya disarankan: ambil halaman data berikutnya. Table.GenerateByPage
akan berulang kali memanggil getNextPage
fungsi, setiap kali melewatinya hasil yang dihasilkan terakhir kali dipanggil, sampai kembali null
ke sinyal kembali bahwa tidak ada lagi halaman yang tersedia.
Karena fungsi ini bukan bagian dari pustaka standar Power Query, Anda harus menyalin kode sumbernya ke dalam file .pq Anda.
Menerapkan GetAllPagesByNextLink
Isi fungsi Anda GetAllPagesByNextLink
mengimplementasikan getNextPage
argumen fungsi untuk Table.GenerateByPage
. Ini akan memanggil GetPage
fungsi, dan mengambil URL untuk halaman data berikutnya dari NextLink
bidang meta
rekaman dari panggilan sebelumnya.
// 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
);
Menerapkan GetPage
Fungsi Anda GetPage
akan menggunakan Web.Contents untuk mengambil satu halaman data dari layanan TripPin, dan mengonversi respons menjadi tabel. Ini meneruskan respons dari Web.Contents ke GetNextLink
fungsi untuk mengekstrak URL halaman berikutnya, dan mengaturnya pada meta
rekaman tabel yang dikembalikan (halaman data).
Implementasi ini adalah versi TripPin.Feed
panggilan yang sedikit dimodifikasi dari tutorial sebelumnya.
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];
Menerapkan GetNextLink
Fungsi Anda GetNextLink
hanya memeriksa isi respons untuk bidang @odata.nextLink
, dan mengembalikan nilainya.
// 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");
Merangkum semuanya
Langkah terakhir untuk mengimplementasikan logika halaman Anda adalah memperbarui TripPin.Feed
untuk menggunakan fungsi baru. Untuk saat ini, Anda hanya menelepon ke GetAllPagesByNextLink
, tetapi dalam tutorial berikutnya, Anda akan menambahkan kemampuan baru (seperti memberlakukan skema, dan logika parameter kueri).
TripPin.Feed = (url as text) as table => GetAllPagesByNextLink(url);
Jika Anda menjalankan kembali kueri pengujian yang sama dari sebelumnya dalam tutorial, Anda sekarang akan melihat pembaca halaman beraksi. Anda juga akan melihat bahwa Anda memiliki 24 baris dalam respons daripada delapan.
Jika Anda melihat permintaan di fiddler, Anda sekarang akan melihat permintaan terpisah untuk setiap halaman data.
Catatan
Anda akan melihat permintaan duplikat untuk halaman pertama data dari layanan, yang tidak ideal. Permintaan tambahan adalah hasil dari perilaku pemeriksaan skema mesin M. Abaikan masalah ini untuk saat ini dan selesaikan di tutorial berikutnya, di mana Anda akan menerapkan skema eksplisit.
Kesimpulan
Pelajaran ini menunjukkan kepada Anda cara menerapkan dukungan penomoran halaman untuk Rest API. Meskipun logika kemungkinan akan bervariasi antara API, pola yang ditetapkan di sini harus dapat digunakan kembali dengan modifikasi kecil.
Dalam pelajaran berikutnya, Anda akan melihat cara menerapkan skema eksplisit ke data Anda, melampaui jenis data sederhana text
dan number
yang Anda dapatkan dari Json.Document
.