Shopify용 Openflow Connector의 객체 정의 오버라이드
Shopify용 Openflow Connector의 객체 정의 오버라이드
이 페이지에서는 Object Definitions Override 파라미터를 자세히 설명해요. 전체 스키마, 승격 열(promoted column)과 하위 필드 정의, 그리고 완전한 예시를 포함합니다. Shopify 객체를 사용자 정의로 확장하거나 바꿔치기하려는 경우 유용합니다.
출처: Snowflake 문서
본문
Note
이 커넥터는 Snowflake Connector Terms에 의해 규율됩니다.
이 토픽은 Object Definitions Override 파라미터를 상세히 설명합니다. 전체 스키마, 승격 열과 하위 필드 정의, 그리고 완전한 예시를 포함해요.
Object Definitions Override 파라미터는 객체 정의의 JSON 배열을 받습니다. 각 정의는 새 객체 유형을 추가하거나 기존 카탈로그 항목을 완전히 교체할 수 있습니다.
객체 정의 스키마
Important
Object Definitions Override 값은 유효한 JSON이어야 합니다. JSON이 잘못되면 커넥터가 시작에 실패합니다. 오버라이드를 적용하기 전에 JSON을 검증하세요.
각 객체 정의에서 지원되는 필드는 다음과 같습니다:
| Field | Description |
|---|---|
| apiType | (필수) Shopify Admin GraphQL API의 쿼리 엔드포인트 이름. 루트 쿼리 필드와 정확히 일치해야 합니다(예: orders 쿼리는 orders, products 쿼리는 products). 조회·오버라이드 매칭의 키로 사용됩니다. |
| tableName | (필수) Snowflake 대상 테이블 이름. |
| gidTypeName | Shopify GID 리소스 유형(예: Order, Product). 삭제 전파와 하위 레코드 라우팅에 사용됩니다. |
| additionalGidTypeNames | 이 객체에도 매핑되는 추가 GID 유형 이름의 배열. Shopify가 같은 리소스를 두 개 이상의 GID 유형 이름으로 반환할 때 사용하여, 응답에 어떤 GID 유형이 나타나든 레코드를 올바른 테이블로 라우팅합니다. |
| graphqlFields | GraphQL 선택 필드 목록. 각 항목은 필드 이름, 중첩 선택(예: "totalPriceSet { shopMoney { amount currencyCode } }"), 또는 인자를 가진 별칭 필드(예: "tier: metafield(key: \"custom.tier\") { value }")입니다. 별칭은 키로 메타필드를 조회할 때 유용합니다. |
| requiredQueryArgs | 이 객체의 모든 쿼리에 추가되는 고정 GraphQL 인자 키-값 쌍의 맵. 내장 쿼리 파라미터로 다루지 않는 비표준 인자가 필요한 엔드포인트에 사용합니다(예: {"type": "SALES_CHANNEL"}). |
| supportsIncremental | 객체가 증분 동기화를 지원하는지 여부. 기본값: true. |
| incrementalField | 워터마크 기반 증분 쿼리에 사용되는 필드(예: updatedAt, createdAt). 이 필드는 반환된 타입에 존재해야 하며, 쿼리 루트의 query: 인자로 필터도 허용되어야 합니다. 타입에는 존재하지만 필터로 지원되지 않는 필드는 GetShopifyIncremental이 Invalid search field: <name>으로 실패하게 합니다. 이런 경우 supportsIncremental을 false로, refreshStrategy를 FULL_PERIODIC으로 설정하세요. |
| refreshStrategy | 동기화 모드를 제어합니다. INCREMENTAL(기본)은 워터마크 기반 증분 쿼리를, FULL_PERIODIC은 매 실행마다 전체 재동기화를 수행합니다. PARENT_PIGGYBACKED는 이 객체가 다른 객체의 쿼리 응답에서 추출되며 독립적으로 조회되지 않음을 의미합니다. |
| supportsDeletes | 커넥터가 이 객체의 삭제 이벤트를 추적할지 여부. 기본값: false. |
| promotedColumns | JSON 페이로드에서 값을 추출해 전용 Snowflake 열로 만드는 열 정의 배열. 자세한 내용은 Promoted columns를 참고하세요. |
| childFields | 별도 테이블로 추출되는 하위 연결 정의 배열. 자세한 내용은 Child fields를 참고하세요. |
| ignoredFields | 쿼리에서 제외할 필드 이름 목록. graphqlFields의 각 최상위 항목의 선행 이름에만 일치합니다. 하위 선택 내부의 중첩 필드(예: defaultEmailAddress { ... } 안의 필드)에는 ignoredFields가 적용되지 않습니다. 대신 graphqlFields의 하위 선택에서 해당 필드를 직접 제거하세요. |
| supportsBulk | 객체가 Shopify Bulk Operations API를 통한 벌크 쿼리를 지원하는지 여부. 기본값: true. |
| sortKeys | 벌크·증분 쿼리 중 결과를 정렬하는 데 사용하는 정렬 키 값 목록(객체의 해당 SortKeys 열거형에서). 예: ["UPDATED_AT", "ID"]. |
| sortKeyStyle | 쿼리에서 정렬 키 값이 형식화되는 방식. ENUM(기본)은 대문자 열거형 값(예: UPDATED_AT)을, STRING은 따옴표로 감싼 소문자 문자열(예: "updated_at")을 사용합니다. 메타오브젝트처럼 문자열 정렬 키를 받는 객체 유형에는 STRING을 사용하세요. |
승격 열 (Promoted columns)
승격 열은 원시 JSON 페이로드에서 특정 값을 추출해 대상 테이블의 전용 타입 열로 만듭니다. 이렇게 하면 자주 조회하는 필드를 일급 Snowflake 열로 사용할 수 있어 효율적인 필터링·집계가 가능합니다.
각 승격 열은 다음 필드를 가집니다:
| Field | Description |
|---|---|
| name | Snowflake 열 이름(대문자 권장). |
| path | 원시 레코드에서 값을 가리키는 JSONPath 표현식(예: $.email, $.totalPriceSet.shopMoney.amount). |
| type | Snowflake 열 유형. 다음 값이 지원됩니다: |
| Value | Snowflake type | Notes |
|---|---|---|
| string | VARCHAR | None |
| integer | NUMBER(38,0) | None |
| boolean | BOOLEAN | None |
| float | FLOAT | None |
| money | NUMBER(38,4) | Shopify 금액 문자열을 숫자로 변환. |
| timestamp | TIMESTAMP_TZ | ISO-8601 문자열. |
| date | DATE | None |
| id | NUMBER(38,0) | gid://shopify/*/ 접두사를 제거하고 숫자 ID를 반환. |
| gid | VARCHAR | 전체 GID 문자열을 저장. |
| json | VARIANT | 하위 객체를 VARIANT로 저장. |
하위 필드 (Child fields)
하위 필드 정의는 중첩 연결(예: 주문 라인 아이템)을 별도 Snowflake 테이블로 추출합니다. 각 하위 테이블에는 레코드를 부모로 연결하는 __PARENT_ID 열이 포함됩니다.
각 하위 필드는 다음 필드를 가집니다:
| Field | Description |
|---|---|
| fieldName | 부모 객체의 GraphQL 연결 필드 이름(예: lineItems). |
| tableName | 하위 레코드의 Snowflake 테이블 이름. |
| gidTypeName | 하위 항목의 Shopify GID 유형(예: LineItem). |
| connectionType | edges(페이지네이션 연결) 또는 array(인라인 배열). 기본값: edges. |
| pageSize | 증분 쿼리에서 이 하위 연결에 적용되는 first: 한도. 기본값·최대값: 250. |
| graphqlFields | 하위 테이블의 명시적 GraphQL 선택 집합. 생략하면 커넥터가 부모의 graphqlFields 목록에서 일치하는 연결 항목으로 하위 필드를 파싱합니다. |
| promotedColumns | 최상위 promotedColumns와 같은 스키마를 사용하는 하위 테이블용 승격 열 정의 배열. |
Note
Shopify는 250을 초과하는 pageSize 값을 first cannot exceed 250 오류로 거부합니다. 이 한도는 벌크 로드에는 적용되지 않습니다: Shopify Bulk Operations API는 first: 인자를 무시하고 모든 하위 레코드를 반환합니다. 자세한 내용은 Limitations를 참고하세요.
유니온 타입과 GID 라우팅
쿼리 루트가 유니온 타입을 반환하면 Shopify Bulk API 응답의 레코드는 쿼리 루트 이름이나 GraphQL 유니온 타입 이름이 아니라 구체적인 래퍼 노드 타입에 해당하는 GID 유형을 지닙니다. 커넥터의 PartitionShopifyByObject 프로세서는 GID 유형으로 레코드를 라우팅하므로, GID 유형이 gidTypeName 또는 additionalGidTypeNames에 등록되지 않으면 레코드는 실패로 라우팅됩니다.
예를 들어 discountNodes 쿼리 루트는 Discount 유니온을 반환합니다. 응답의 레코드는 DiscountNode나 Discount가 아니라 DiscountCodeNode와 DiscountAutomaticNode GID 유형을 지닙니다. 모든 레코드를 같은 테이블로 라우팅하려면 gidTypeName을 하나의 구체적 타입으로 설정하고 나머지를 additionalGidTypeNames에 나열하세요.
다음 예시는 discountNodes를 올바르게 구성합니다:
[
{
"apiType": "discountNodes",
"tableName": "DISCOUNTS",
"gidTypeName": "DiscountCodeNode",
"additionalGidTypeNames": ["DiscountAutomaticNode"],
"graphqlFields": [
"id",
"discount { ... on DiscountCodeBasic { title status startsAt endsAt createdAt updatedAt } ... on DiscountAutomaticBasic { title status startsAt endsAt createdAt updatedAt } }"
]
}
]
Note
유니온 타입 객체에서 promotedColumns를 사용할 때, 파티셔닝 후 JSON 루트는 래퍼 노드입니다(예: { id, discount: { … } }), 내부 유니온 멤버가 아닙니다. 승격 열 path 값에는 래퍼 필드가 포함되어야 합니다(예: $.title이 아니라 $.discount.title).
증분 지원과 함께 할인을 동기화하려면 codeDiscountNodes나 automaticDiscountNodes보다 discountNodes를 사용하세요. 하위 유형별 쿼리 루트는 updated_at을 필터로 받아들이지 않아서 supportsIncremental: false와 refreshStrategy: "FULL_PERIODIC"가 필요합니다.
정의를 작성하기 전에 실제 응답에 어떤 GID 유형이 나타나는지 확인하려면 작은 테스트 벌크 로드를 실행하거나, 쿼리 루트가 반환하는 구체적 타입에 대한 Shopify 문서를 확인하세요.
예시: 승격 열과 함께 사용자 정의 객체 유형 등록
다음 오버라이드는 기존 카탈로그 항목을 사용자 정의해 스칼라 필드, 중첩 객체 선택, 메타필드 별칭, 승격 열을 추가합니다. 하나의 승격 열은 별칭이 붙은 메타필드에서 값을 직접 추출합니다.
[
{
"apiType": "draftOrders",
"tableName": "DRAFT_ORDERS",
"gidTypeName": "DraftOrder",
"supportsBulk": true,
"supportsIncremental": true,
"incrementalField": "updatedAt",
"ignoredFields": [],
"sortKeys": ["UPDATED_AT", "ID"],
"supportsDeletes": false,
"graphqlFields": [
"id",
"createdAt",
"updatedAt",
"name",
"status",
"email",
"currencyCode",
"totalQuantityOfLineItems",
"customer { id }",
"totalPriceSet { shopMoney { amount currencyCode } }",
"billingAddress { address1 city countryCode zip }",
"draft_po_number: metafield(key: \"custom.draft_po_number\") { key namespace compareDigest createdAt id jsonValue legacyResourceId updatedAt value definition { id description key pinnedPosition } }"
],
"promotedColumns": [
{ "name": "STATUS", "path": "$.status", "type": "string" },
{ "name": "NAME", "path": "$.name", "type": "string" },
{ "name": "CUSTOMER_ID", "path": "$.customer.id", "type": "gid" },
{ "name": "TOTAL_PRICE_AMOUNT", "path": "$.totalPriceSet.shopMoney.amount", "type": "money" },
{ "name": "DRAFT_PO_NUMBER", "path": "$.draft_po_number.value", "type": "string" }
],
"childFields": []
}
]
예시: 하위 필드가 있는 객체 오버라이드
다음 오버라이드는 orders 객체를 사용자 정의해 라인 아이템과 주문 처리를 별도 테이블로 추출합니다. 라인 아이템은 페이지네이션 연결(edges)을, 주문 처리는 부모 응답의 인라인 배열(array)을 사용합니다.
[
{
"apiType": "orders",
"tableName": "ORDERS",
"gidTypeName": "Order",
"graphqlFields": [
"id",
"createdAt",
"updatedAt",
"name",
"email",
"lineItems(first: 250) { edges { cursor node { id title quantity originalUnitPriceSet { shopMoney { amount currencyCode } } } } }",
"fulfillments { id status createdAt }"
],
"childFields": [
{
"fieldName": "lineItems",
"tableName": "ORDER_LINE_ITEMS",
"gidTypeName": "LineItem",
"connectionType": "edges"
},
{
"fieldName": "fulfillments",
"tableName": "ORDER_FULFILLMENTS",
"gidTypeName": "Fulfillment",
"connectionType": "array"
}
]
}
]