스키마 처리
데이터 원본에 따라 데이터 형식 및 열 이름에 대한 정보가 명시적으로 제공되거나 제공되지 않을 수 있습니다. OData REST API는 일반적으로 $metadata 정의를 사용하여 이를 처리하며 파워 쿼리 OData.Feed
메서드는 자동으로 이 정보를 구문 분석하고 OData 원본에서 반환된 데이터에 적용합니다.
대부분의 REST API는 해당 스키마를 프로그래밍 방식으로 확인할 방법이 없습니다. 이러한 경우 커넥터에 스키마 정의를 포함해야 합니다.
가장 간단한 방법은 스키마 정의를 커넥터에 하드 코딩하는 것입니다. 이는 대부분의 사용 사례에 충분합니다.
전반적으로 커넥터에서 반환된 데이터에 스키마를 적용하면 다음과 같은 여러 이점이 있습니다.
- 올바른 데이터 형식 설정
- 최종 사용자에게 표시할 필요가 없는 열 제거(예: 내부 ID 또는 상태 정보).
- 응답에서 누락될 수 있는 열을 추가하여 데이터의 각 페이지에 동일한 셰이프가 있는지 확인합니다(REST API는 일반적으로 필드를 완전히 생략하여 필드가 null이어야 함을 나타냅니다).
TripPin OData 샘플 서비스에서 간단한 테이블을 반환하는 다음 코드를 고려합니다.
let
url = "https://services.odata.org/TripPinWebApiService/Airlines",
source = Json.Document(Web.Contents(url))[value],
asTable = Table.FromRecords(source)
in
asTable
참고
TripPin은 OData 원본이므로 현실적으로 함수의 자동 스키마 처리를 사용하는 OData.Feed
것이 더 합리적입니다. 이 예제에서는 원본을 일반적인 REST API로 처리하고 Web.Contents
스키마를 직접 하드 코딩하는 기술을 보여 줍니다.
이 테이블은 결과입니다.
편리한 Table.Schema
함수를 사용하여 열의 데이터 형식을 확인할 수 있습니다.
let
url = "https://services.odata.org/TripPinWebApiService/Airlines",
source = Json.Document(Web.Contents(url))[value],
asTable = Table.FromRecords(source)
in
Table.Schema(asTable)
AirlineCode와 Name은 모두 형식입니다 any
. Table.Schema
는 이름, 위치, 형식 정보 및 Precision, Scale 및 MaxLength와 같은 많은 고급 속성을 포함하여 테이블의 열에 대한 많은 메타데이터를 반환합니다. 지금은 기록된 형식(), 기본 형식(TypeName
) 및 열 값이 nullIsNullable
(Kind
)일 수 있는지 여부만 고려해야 합니다.
스키마 테이블은 다음 두 개의 열로 구성됩니다.
Column | 세부 정보 |
---|---|
속성 | 열 이름입니다. 서비스에서 반환한 결과의 이름과 일치해야 합니다. |
Type | 설정할 M 데이터 형식입니다. 기본 형식(텍스트, 숫자, 날짜/시간 등) 또는 지정된 형식(Int64.Type, Currency.Type 등)일 수 있습니다. |
테이블에 대한 Airlines
하드 코딩된 스키마 테이블은 테이블 AirlineCode
과 Name
열을 text
다음과 같이 설정합니다.
Airlines = #table({"Name", "Type"}, {
{"AirlineCode", type text},
{"Name", type text}
})
다른 엔드포인트 중 일부를 살펴보면 다음 스키마 테이블을 고려합니다.
Airports
테이블에는 유지할 필드가 4개 있습니다(형식 record
중 하나 포함).
Airports = #table({"Name", "Type"}, {
{"IcaoCode", type text},
{"Name", type text},
{"IataCode", type text},
{"Location", type record}
})
테이블에는 People
s(, AddressInfo
), nullable 열(Emails
) 및 Ascribed 형식이 있는 열(Gender
Concurrency
)을 포함하여 list
7개의 필드가 있습니다.
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}
})
이러한 모든 테이블을 단일 마스터 스키마 테이블에 SchemaTable
넣을 수 있습니다.
SchemaTable = #table({"Entity", "SchemaTable"}, {
{"Airlines", Airlines},
{"Airports", Airports},
{"People", People}
})
SchemaTransformTable
아래에 설명된 도우미 함수는 데이터에 스키마를 적용하는 데 사용됩니다. 사용되는 매개 변수는 다음과 같습니다.
매개 변수 | 형식 | 설명 |
---|---|---|
table | table | 스키마를 적용할 데이터 테이블입니다. |
schema(스키마) | table | 열 정보를 읽을 스키마 테이블입니다. 형식은 다음과 같습니다 type table [Name = text, Type = type] . |
enforceSchema | number | (선택 사항) 함수의 동작을 제어하는 열거형입니다. 기본값( EnforceSchema.Strict = 1 )은 누락된 열을 추가하고 추가 열을 제거하여 출력 테이블이 제공된 스키마 테이블과 일치하도록 합니다. 이 EnforceSchema.IgnoreExtraColumns = 2 옵션은 결과에 추가 열을 유지하는 데 사용할 수 있습니다. 사용되는 경우 EnforceSchema.IgnoreMissingColumns = 3 누락된 열과 추가 열은 모두 무시됩니다. |
이 함수의 논리는 다음과 같습니다.
- 원본 테이블에서 누락된 열이 있는지 확인합니다.
- 추가 열이 있는지 확인합니다.
- 구조화된 열(형식
list
,record
및 ) 및table
형식any
으로 설정된 열을 무시합니다. - 각 열 형식을 설정하는 데 사용합니다
Table.TransformColumnTypes
. - 스키마 테이블에 표시되는 순서에 따라 열의 순서를 다시 지정합니다.
- 를 사용하여
Value.ReplaceType
테이블 자체의 형식을 설정합니다.
참고
테이블 형식을 설정하는 마지막 단계에서는 쿼리 편집기에서 결과를 볼 때 파워 쿼리 UI에서 형식 정보를 유추할 필요가 없어지며, 이로 인해 API에 대한 두 번 호출이 발생할 수 있습니다.
전체 확장의 더 큰 컨텍스트에서는 테이블이 API에서 반환될 때 스키마 처리가 수행됩니다. 일반적으로 이 기능은 탐색 테이블에서 전달된 엔터티 정보를 사용하여 페이징 함수의 가장 낮은 수준(있는 경우)에서 수행됩니다.
페이징 및 탐색 테이블의 구현은 대부분 컨텍스트별로 지정되므로 하드 코딩된 스키마 처리 메커니즘을 구현하는 전체 예제는 여기에 표시되지 않습니다. 이 TripPin 예제 에서는 엔드 투 엔드 솔루션의 모양을 보여 줍니다.
위에서 설명한 하드 코딩된 구현은 간단한 JSON 회신에 대해 스키마가 일관성을 유지하도록 하는 좋은 작업을 수행하지만 응답의 첫 번째 수준을 구문 분석하는 것으로 제한됩니다. 깊이 중첩된 데이터 세트는 M 형식을 활용하는 다음 접근 방식의 이점을 누릴 수 있습니다.
다음은 언어 사양에서 M 언어의 형식에 대한 빠른 새로 고침입니다.
형식 값은 다른 값을 분류하는 값입니다. 형식으로 분류되는 값은 해당 형식을 준수한다고 합니다. M 형식 시스템은 다음과 같은 종류의 형식으로 구성됩니다.
- 기본 형식은 기본값(
binary
, ,,date
,datetime
,datetimezone
,null
type
list
time
logical
number
record
duration
text
) 을 분류하고 여러 추상 형식(function
, ,table
any
및none
)도 포함합니다.- 필드 이름 및 값 형식에 따라 레코드 값을 분류하는 레코드 형식입니다.
- 단일 항목 기본 형식을 사용하여 목록을 분류하는 목록 형식입니다.
- 매개 변수 형식 및 반환 값을 기반으로 함수 값을 분류하는 함수 형식입니다.
- 열 이름, 열 형식 및 키를 기반으로 테이블 값을 분류하는 테이블 형식입니다.
- 기본 형식으로 분류된 모든 값 외에 null 값을 분류하는 Null 허용 형식입니다.
- 형식인 값을 분류하는 형식 형식입니다.
가져오는 원시 JSON 출력(및/또는 서비스의 $metadata 정의를 조회하여)을 사용하여 OData 복합 형식을 나타내는 다음 레코드 형식을 정의할 수 있습니다.
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
];
구조화된 CityType
열을 참조하고 LocType
나타내는 방법을 LocationType
확인합니다.
테이블로 나타낼 최상위 엔터티의 경우 테이블 형식을 정의할 수 있습니다.
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
];
그런 다음, 다음과 같은 새 형식 정의를 사용하도록 변수(엔터티-형식 매핑에 대한 조회 테이블로 사용할 수 있는)를 업데이트 SchemaTable
할 수 있습니다.
SchemaTable = #table({"Entity", "Type"}, {
{"Airlines", AirlinesType},
{"Airports", AirportsType},
{"People", PeopleType}
});
이전 연습에서 사용한 SchemaTransformTable
것처럼 공통 함수(Table.ChangeType
)를 사용하여 데이터에 스키마를 적용할 수 있습니다. 달리 SchemaTransformTable
실제 Table.ChangeType
M 테이블 형식을 인수로 사용하고 모든 중첩된 형식에 대해 스키마 를 재귀적으로 적용합니다. 해당 시그니처는 다음과 같습니다.
Table.ChangeType = (table, tableType as type) as nullable table => ...
참고
유연성을 위해 테이블과 레코드 목록(테이블이 JSON 문서에 표시되는 방식)에서 함수를 사용할 수 있습니다.
그런 다음 커넥터 코드를 업데이트하여 매개 변수를 a에서 a table
type
로 변경 schema
하고 호출을 추가해야 합니다Table.ChangeType
. 다시 말하지만, 이에 대한 세부 사항은 구현에 따라 매우 구체적이므로 여기에서 자세히 살펴볼 가치가 없습니다. 이 확장된 TripPin 커넥터 예제 에서는 스키마를 처리하는 보다 정교한 방법을 구현하는 엔드 투 엔드 솔루션을 보여 줍니다.