Séma kezelése
Az adatforrástól függően előfordulhat, hogy az adattípusokra és az oszlopnevekre vonatkozó információk kifejezetten megadhatók vagy nem. Az OData REST API-k általában a $metadata definícióval kezelik ezt, a Power Query OData.Feed
metódus pedig automatikusan kezeli ezeket az információkat, és alkalmazza azokat az OData-forrásból visszaadott adatokra.
Sok REST API nem tudja programozott módon meghatározni a sémáját. Ezekben az esetekben sémadefiníciót kell tartalmaznia az összekötőben.
A legegyszerűbb módszer a sémadefiníciók az összekötőbe való kódolása. Ez a legtöbb használati esetben elegendő.
Általánosságban elmondható, hogy az összekötő által visszaadott adatok sémájának kényszerítése több előnnyel is jár, például:
- A megfelelő adattípusok beállítása.
- Eltávolítja azokat az oszlopokat, amelyeket nem kell megjeleníteni a végfelhasználók számára (például belső azonosítókat vagy állapotinformációkat).
- A válaszból esetleg hiányzó oszlopok hozzáadásával biztosíthatja, hogy minden adatoldal azonos alakú legyen (a REST API-k általában azt jelzik, hogy a mezőknek null értékűnek kell lenniük, ha teljesen kihagyják őket).
Vegye figyelembe az alábbi kódot, amely egy egyszerű táblát ad vissza a TripPin OData mintaszolgáltatásból:
let
url = "https://services.odata.org/TripPinWebApiService/Airlines",
source = Json.Document(Web.Contents(url))[value],
asTable = Table.FromRecords(source)
in
asTable
Megjegyzés
A TripPin egy OData-forrás, ezért reálisabban érdemes a függvény automatikus sémakezelését használni OData.Feed
. Ebben a példában a forrást egy tipikus REST API-ként fogja kezelni, és Web.Contents
a sémák kézzel történő keménykódolásának technikáját mutatja be.
Ez a táblázat az eredmény:
A hasznos Table.Schema
függvénnyel ellenőrizheti az oszlopok adattípusát:
let
url = "https://services.odata.org/TripPinWebApiService/Airlines",
source = Json.Document(Web.Contents(url))[value],
asTable = Table.FromRecords(source)
in
Table.Schema(asTable)
Az AirlineCode és a Name típus is any
. Table.Schema
Sok metaadatot ad vissza a tábla oszlopairól, beleértve a neveket, a pozíciókat, a típusadatokat és számos speciális tulajdonságot, például a pontosságot, a méretezést és a MaxLengthet. Egyelőre csak az írott típus (), a primitív típus (TypeName
Kind
) és az oszlop értéke lehet null (IsNullable
).
A sématábla két oszlopból áll:
Oszlop | Részletek |
---|---|
Név | Az oszlop neve. Ennek meg kell egyeznie a szolgáltatás által visszaadott eredményekben szereplő névvel. |
Típus | A beállítani kívánt M adattípus. Ez lehet egy primitív típus (szöveg, szám, dátum/idő stb.), vagy egy írott típus (Int64.Type, Currency.Type stb.). |
A tábla rögzített sématáblája a Airlines
következőképpen állítja be és Name
állítja be az AirlineCode
oszlopokattext
:
Airlines = #table({"Name", "Type"}, {
{"AirlineCode", type text},
{"Name", type text}
})
A többi végpontot tekintve vegye figyelembe a következő sématáblákat:
A Airports
tábla négy megtartandó mezővel rendelkezik (beleértve a típus record
egyikét):
Airports = #table({"Name", "Type"}, {
{"IcaoCode", type text},
{"Name", type text},
{"IataCode", type text},
{"Location", type record}
})
A People
táblázat hét mezővel rendelkezik, beleértve list
az s (Emails
, AddressInfo
), a null értékű oszlopot (Gender
), és egy írott típusú (Concurrency
) oszlopot:
People = #table({"Name", "Type"}, {
{"UserName", type text},
{"FirstName", type text},
{"LastName", type text},
{"Emails", type list},
{"AddressInfo", type list},
{"Gender", type nullable text},
{"Concurrency", Int64.Type}
})
Ezeket a táblákat egyetlen fő sématáblába SchemaTable
helyezheti:
SchemaTable = #table({"Entity", "SchemaTable"}, {
{"Airlines", Airlines},
{"Airports", Airports},
{"People", People}
})
Az SchemaTransformTable
alábbiakban ismertetett segédfüggvény a sémák kikényszerítésére szolgál az adatokon. A következő paramétereket veszi igénybe:
Paraméter | Típus | Leírás |
---|---|---|
table | table | Azon adattábla, amelyen a sémát érvényesíteni szeretné. |
schema | table | Az oszlopinformációkat beolvasni kívánt sématábla a következő típussal: type table [Name = text, Type = type] . |
enforceSchema | szám | (nem kötelező) A függvény viselkedését vezérlő szám. Az alapértelmezett érték ( EnforceSchema.Strict = 1 ) biztosítja, hogy a kimeneti tábla megegyezik a hiányzó oszlopok hozzáadásával és a további oszlopok eltávolításával megadott sématáblával. Ezzel EnforceSchema.IgnoreExtraColumns = 2 a beállítással megőrizheti a további oszlopokat az eredményben. A használat során EnforceSchema.IgnoreMissingColumns = 3 a rendszer figyelmen kívül hagyja a hiányzó oszlopokat és a további oszlopokat is. |
A függvény logikája a következőképpen néz ki:
- Állapítsa meg, hogy vannak-e hiányzó oszlopok a forrástáblából.
- Állapítsa meg, hogy vannak-e további oszlopok.
- Figyelmen kívül hagyja a strukturált oszlopokat (típus
list
record
, és ) éstable
a típusraany
beállított oszlopokat. - Az egyes oszloptípusok beállítására használható
Table.TransformColumnTypes
. - Az oszlopok átrendezése a sématáblában megjelenő sorrend alapján.
- Állítsa be magát a típust a táblán a következővel
Value.ReplaceType
: .
Megjegyzés
A táblatípus beállításának utolsó lépése megszünteti, hogy a Power Query felhasználói felülete típusadatokat vonjon le a lekérdezésszerkesztőben az eredmények megtekintésekor, ami néha dupla hívást eredményezhet az API-hoz.
A teljes bővítmény nagyobb kontextusában a sémakezelés akkor történik meg, amikor a rendszer visszaad egy táblát az API-ból. Ez a funkció általában a lapozófüggvény legalsó szintjén (ha létezik) történik, és egy navigációs táblából továbbított entitásadatokkal.
Mivel a lapozási és navigációs táblák implementálásának nagy része környezetfüggő, itt nem jelenik meg a szigorúan kódolt sémakezelő mechanizmus implementálásának teljes példája. Ez a TripPin-példa bemutatja, hogyan nézhet ki egy végpontok közötti megoldás.
A fent tárgyalt kemény kóddal ellátott implementáció jó feladat annak biztosításához, hogy a sémák konzisztensek maradjanak az egyszerű JSON-repsonok esetében, de ez a válasz első szintjének elemzésére korlátozódik. A mélyen beágyazott adathalmazok az alábbi megközelítés előnyeit élvezik, amely kihasználja az M-típusok előnyeit.
Íme egy gyors frissítés az M nyelv típusairól a Nyelvi specifikációból:
A típusérték olyan érték, amely más értékeket sorol be . A típus szerint besorolt értéknek az adott típusnak kell megfelelnie . Az M típusú rendszer a következő típusokból áll:
- Primitív típusok, amelyek primitív értékeket osztályoznak (
binary
,date
, ,datetimezone
duration
datetime
,list
logical
number
record
null
, ,text
, ),time
),type
és számos absztrakt típust is tartalmaznak (function
,table
, ,any
és ).none
- Rekordtípusok, amelyek mezőnevek és értéktípusok alapján osztályozzák a rekordértékeket.
- Listatípusok, amelyek egyetlen elem alaptípusával osztályozzák a listákat.
- Függvénytípusok, amelyek a paraméterek típusai alapján osztályozzák a függvényértékeket, és visszaadják az értékeket.
- Táblázattípusok, amelyek oszlopnevek, oszloptípusok és kulcsok alapján sorolják be a táblaértékeket.
- Null értékű típusok, amelyek az alaptípus szerint besorolt értékek mellett a null értéket is osztályozzák.
- Típustípusok, amelyek a típusokat osztályozzák.
A nyers JSON-kimenet használatával (és/vagy a szolgáltatás $metadata definícióinak megtekintésével) a következő rekordtípusokat határozhatja meg az OData-összetett típusok megjelenítéséhez:
LocationType = type [
Address = text,
City = CityType,
Loc = LocType
];
CityType = type [
CountryRegion = text,
Name = text,
Region = text
];
LocType = type [
#"type" = text,
coordinates = {number},
crs = CrsType
];
CrsType = type [
#"type" = text,
properties = record
];
Figyelje meg, hogyan hivatkozik a CityType
strukturált oszlopokra, és LocType
hogyan LocationType
jeleníti meg azokat.
Azoknak a legfelső szintű entitásoknak, amelyeket táblákként szeretne ábrázolni, a következő táblázattípusokat határozhatja meg:
AirlinesType = type table [
AirlineCode = text,
Name = text
];
AirportsType = type table [
Name = text,
IataCode = text,
Location = LocationType
];
PeopleType = type table [
UserName = text,
FirstName = text,
LastName = text,
Emails = {text},
AddressInfo = {nullable LocationType},
Gender = nullable text,
Concurrency Int64.Type
];
Ezután frissítheti a változót SchemaTable
(amelyet entitások közötti leképezések keresési táblájaként használhat) az alábbi új típusdefiníciók használatára:
SchemaTable = #table({"Entity", "Type"}, {
{"Airlines", AirlinesType},
{"Airports", AirportsType},
{"People", PeopleType}
});
Egy általános függvényre (Table.ChangeType
) támaszkodva kényszerítheti ki a sémát az adataira, hasonlóan a korábbi gyakorlatban használthoz SchemaTransformTable
. Ellentétben SchemaTransformTable
a Table.ChangeType
tényleges M táblatípussal argumentumként, és rekurzív módon alkalmazza a sémát az összes beágyazott típusra. Aláírása:
Table.ChangeType = (table, tableType as type) as nullable table => ...
Megjegyzés
A rugalmasság érdekében a függvény táblákon és rekordlistákon is használható (így jelennek meg a táblák egy JSON-dokumentumban).
Ezután frissítenie kell az összekötő kódját, hogy a schema
paramétert egyről egyre table
type
módosítsa, és fel kell vennie egy hívást.Table.ChangeType
Ennek részletei szintén nagyon implementációspecifikusak, ezért itt nem érdemes részletesen tárgyalni. Ez a kiterjesztett TripPin-összekötő-példa egy teljes körű megoldást mutat be, amely implementálja ezt a kifinomultabb módszert a séma kezeléséhez.