Keyboard shortcuts

Press ← or → to navigate between chapters

Press ? to show this help

Press Esc to hide this help

TypeScript OSDK 2.x 참조

TypeScript OSDK는 생성한 객체, 액션과 쿼리 정의를 인증된 Client에 전달하여 호출합니다. 이 장의 예제 패키지는 가상 @my-app/sdk입니다. 앱이 사용할 리소스를 Developer Console에 추가하고 실제 생성 패키지 및 인증 설정으로 바꿔야 합니다.

예제 스키마

표시 이름API 이름자료형
Restaurant Id, 기본 키restaurantIdString
Restaurant Name, 제목restaurantNameString
AddressaddressString
EmaileMailString
Number Of ReviewsnumberOfReviewsInteger
Phone NumberphoneNumberString
Review SummaryreviewSummaryString
Date Of OpeningdateOfOpeningDate

객체 인스턴스 타입은 Osdk.Instance<Restaurant>입니다. 생성 정의 Restaurant 자체는 데이터 인스턴스가 아닙니다. 다른 속성과 링크를 사용하는 예제는 해당 추가 스키마를 따로 설명합니다.

한 객체, 한 페이지와 전체 집합

import { Client, Osdk } from "@osdk/client";
import { Restaurant } from "@my-app/sdk";

export function loadRestaurant(client: Client, primaryKey: string): Promise<Osdk.Instance<Restaurant>> {
    return client(Restaurant).fetchOne(primaryKey);
}

export function loadRestaurantPage(client: Client, nextPageToken?: string) {
    return client(Restaurant).fetchPage({ $pageSize: 30, $nextPageToken: nextPageToken });
}

export async function loadAllRestaurants(client: Client): Promise<Osdk.Instance<Restaurant>[]> {
    const objects: Osdk.Instance<Restaurant>[] = [];
    for await (const restaurant of client(Restaurant).asyncIter()) objects.push(restaurant);
    return objects;
}

fetchPage는 PageResult<Osdk.Instance<Restaurant>>를 반환합니다. data는 해당 페이지의 배열이고 nextPageToken이 있으면 다음 페이지가 있습니다. 페이지 크기보다 적게 왔다는 이유로 끝났다고 판단하지 않습니다.

asyncIter는 다음 페이지를 자동으로 읽습니다. 위 loadAllRestaurants는 결과를 배열에 모으므로 결국 전체 메모리를 사용합니다. 런타임에서 지원하면 Array.fromAsync로 같은 결과를 만들 수 있고, 전체 배열이 필요 없으면 반복자에서 각 객체를 처리합니다.

OSv1(Phonograph)의 객체 로드는 총 10,000개를 넘으면 ObjectsExceededLimit 오류가 발생합니다. OSv2에는 이 로드 결과 개수 제한이 없지만 앱의 메모리와 질의 실행 비용은 남습니다.

조회 옵션

옵션지원 메서드의미
$selectfetchOne, fetchPage, asyncIter가져올 속성 API 이름 배열
$applyModifiersfetchPage, asyncIter속성별 환산기 또는 구조체 주 값 표현 적용
$includeRidfetchOne, fetchPage, asyncIter$rid 포함
$includeAllBaseObjectPropertiesfetchPage, asyncIter인터페이스 조회에서 기반 구체 유형의 모든 속성 포함. 객체 유형 조회에는 효과 없음
$loadPropertySecurityMetadatafetchOne, fetchPage, asyncIter$propertySecurities에 속성 보안 메타데이터 포함
$orderByfetchPage, asyncIter속성별 정렬 또는 KNN의 relevance 정렬
$pageSizefetchPage페이지의 최대 객체 수
$nextPageTokenfetchPage앞선 PageResult의 nextPageToken
$snapshotfetchPage기본 false. true이면 페이지 조회의 기준 뷰를 고정하여 중복 또는 누락을 방지

속성 선택의 $select는 배열이며 집계의 $select 객체와 다릅니다. 생략하면 API의 기본 속성 집합을 읽으며 Vector 속성 등은 포함되지 않습니다. 온톨로지 정의 파생 속성도 명시적으로 선택해야 합니다. withProperties로 추가한 런타임 파생 속성은 $select를 생략하면 포함되며, $select를 쓰면 해당 이름도 넣어야 합니다.

$snapshot: true는 후속 페이지 요청에도 지정합니다. 스냅샷이 만료되거나 백엔드가 페이지 간 불일치를 감지하면 조회가 실패할 수 있습니다. 스트림 기반 객체 유형에는 이 페이지 간 스냅샷 보장이 적용되지 않습니다. asyncIter()는 스냅샷을 요청하며, 페이지 크기를 직접 지정해야 한다면 fetchPage의 $pageSize와 다음 페이지 토큰을 사용합니다.

배열 환산기와 구조체 주 값

$select로 배열을 선택하면 Ontology Manager에 환산기를 설정했어도 전체 배열을 반환합니다. 네이티브 속성과 온톨로지 정의 파생 속성 모두 같은 원칙입니다.

$applyModifiers는 읽는 표현만 바꾸며 저장된 속성이나 파생 계산을 수정하지 않습니다.

modifier반환 표현
applyReducers배열 환산기가 선택한 원소
applyMainValue구조체의 설정된 주 값 필드 또는 필드들
applyReducersAndExtractMainValue구조체 배열에서 원소를 선택한 뒤 그 구조체의 주 값

생성 SDK는 각 속성의 온톨로지 설정이 지원하는 modifier만 허용하고 반환 타입도 바꿉니다. 가상의 Equipment.maintenanceHistory가 선택 Date 배열이고 가장 최근 날짜 환산기를 설정한 경우입니다.

import { Client } from "@osdk/client";
import { Equipment } from "@my-app/sdk";

export function fullMaintenanceHistory(client: Client) {
    return client(Equipment).fetchPage({ $select: ["equipmentId", "maintenanceHistory"] });
}

export function latestMaintenanceDate(client: Client) {
    return client(Equipment).fetchPage({
        $select: ["equipmentId", "maintenanceHistory"],
        $applyModifiers: { maintenanceHistory: "applyReducers" },
    });
}

예제 배열 [2024-01-15, 2024-03-22, 2024-11-01]은 첫 조회에서 string[] | undefined, 두 번째에서는 2024-11-01이라는 string | undefined로 읽힙니다. 전체 값이 필요하면 modifier를 생략합니다.

정렬

$orderBy는 속성 API 이름에 asc 또는 desc를 지정합니다. 다음은 이름 오름차순의 최대 30개를 읽는 함수입니다.

import { Client } from "@osdk/client";
import { Restaurant } from "@my-app/sdk";

export function orderedRestaurants(client: Client) {
    return client(Restaurant).fetchPage({ $orderBy: { restaurantName: "asc" }, $pageSize: 30 });
}

문자열 정렬은 대소문자를 구분하며 숫자, 대문자, 소문자 순서입니다. 예를 들어 Cat이 bat보다 앞에 옵니다. $orderBy: "relevance"는 KNN 검색에서 사용합니다.

링크

객체의 $link에는 링크 API 이름별 접근자가 있습니다. 단일 관계는 fetchOne 또는 fetchOneWithErrors, 다중 관계는 그 자체가 ObjectSet입니다.

가상의 Restaurant.city는 단일 링크, reviews는 다중 링크라고 가정합니다.

import { Client } from "@osdk/client";
import { Restaurant } from "@my-app/sdk";

export async function restaurantLinks(client: Client, primaryKey: string) {
    const restaurant = await client(Restaurant).fetchOne(primaryKey);
    const city = await restaurant.$link.city.fetchOneWithErrors();
    const reviews = await restaurant.$link.reviews.fetchPage({ $pageSize: 30 });
    return { city, reviews };
}

export function reviewsForNamedRestaurants(client: Client) {
    return client(Restaurant).where({ restaurantName: { $isNull: false } }).pivotTo("reviews");
}

단일 링크의 fetchOne은 없으면 예외를 던집니다. fetchOneWithErrors는 { value } 또는 { error }를 반환하며 링크 부재도 다른 실패처럼 error로 들어옵니다. 다중 링크는 asyncIter, where와 aggregate를 사용할 수 있고 집합에서 pivotTo로 탐색한 결과도 집합입니다.

필터

where는 속성 이름에 조건을 지정합니다. 필터, 정렬과 집계에 사용할 속성은 Searchable 설정을 확인해야 합니다. TSv2에서는 미설정 속성을 사용하는 코드가 컴파일되더라도 전문 검색에서 빈 결과를 받을 수 있습니다.

필터지원과 의미
$startsWithString의 대소문자 비구분 접두사. foo는 foobar에 일치하고 barfoo에는 불일치
$containsAnyTerm공백으로 나눈 단어 하나 이상, 순서 무관 및 대소문자 비구분. foo bar는 bar baz에 일치
$containsAllTerms모든 단어, 순서 무관 및 대소문자 비구분. foo bar는 hello foo baz bar에 일치
$containsAllTermsInOrder모든 단어가 같은 순서로 인접해야 함. foo bar는 hello foo bar baz에 일치
$lt, $lte, $gt, $gte숫자, String 및 날짜/시각의 비교
$eqBoolean, 날짜/시각, 숫자와 String의 값 일치
$isNull값의 부재 여부. false 또는 $not으로 존재 조건 구성
$not조건 부정
$and조건 배열의 모두 만족
$or조건 배열 중 하나 이상 만족

날짜와 시각에는 올바른 ISO 문자열을 사용합니다. 한 속성의 상한과 하한은 별도 절을 $and로 결합합니다.

import { Client } from "@osdk/client";
import { Restaurant } from "@my-app/sdk";

export function matchingRestaurants(client: Client) {
    return client(Restaurant).where({ $and: [
        { restaurantName: { $containsAllTerms: "foo bar" } },
        { numberOfReviews: { $gte: 10 } },
        { numberOfReviews: { $lt: 100 } },
    ] });
}

$not이나 $and/$or 안에도 같은 조건 구조를 넣을 수 있습니다. 속성이 응답에 없을 수 있으므로 $isNull 검색 결과를 읽을 때 필수 문자열로 단정하지 않습니다.

집합 연산

같은 객체 유형의 집합은 union, intersect와 subtract로 합집합, 교집합 및 차집합을 만듭니다. 각 메서드는 하나 이상의 집합을 받고 새 집합을 반환하므로 연결할 수 있습니다.

예를 들어 numberOfReviews가 100 이상인 집합과 restaurantName이 있는 집합을 합치거나 교차하거나, 첫 집합에서 두 번째를 제외할 수 있습니다.

최근접 이웃

벡터 속성에 모델을 정의했다면 nearestNeighbors(query, numNeighbors, property)를 사용합니다. query는 모델과 맞는 숫자 벡터 또는 자동으로 임베딩할 텍스트입니다. numNeighbors는 1부터 500이며 객체 수가 더 작으면 있는 객체를 반환합니다.

가상의 Restaurant.embedding을 검색하는 예제입니다.

import { Client } from "@osdk/client";
import { Restaurant } from "@my-app/sdk";

export function similarRestaurants(client: Client) {
    return client(Restaurant).nearestNeighbors("coffee", 5, "embedding")
        .fetchPage({ $orderBy: "relevance" });
}

relevance 정렬을 넣어 관련도 순서와 $score를 받습니다. 이 옵션 없이 검색하면 다섯 객체의 순서를 보장하지 않습니다. 문서 및 질의 벡터의 모델과 차원은 의미 기반 검색의 계약에 맞춥니다.

집계 요청과 결과

aggregate에는 필수 $select와 선택 $groupBy만 넣습니다. 필터는 먼저 where에 지정합니다.

$select 키는 $count 또는 "속성:지표"이며 지표 이름에는 $를 붙이지 않습니다. 값은 unordered, asc나 desc입니다. $groupBy 속성이 둘 이상이면 모든 지표에 unordered를 사용해야 합니다.

import { Client } from "@osdk/client";
import { Restaurant } from "@my-app/sdk";

export function restaurantStats(client: Client) {
    return client(Restaurant).aggregate({ $select: {
        $count: "unordered",
        "numberOfReviews:avg": "unordered",
        "numberOfReviews:max": "unordered",
        "restaurantName:exactDistinct": "unordered",
    } });
}

그룹 없이 호출하면 객체 하나를 반환하며 위 결과는 result.$count, result.numberOfReviews.avg, result.numberOfReviews.max와 result.restaurantName.exactDistinct로 읽습니다. $groupBy가 있으면 평평한 행 배열이 되고 각 행에는 $group과 선택한 지표가 함께 들어갑니다. 일치 객체가 없으면 그룹 배열은 비어 있으므로 첫 행에 접근하기 전에 확인합니다.

지표 지원과 반환 타입

속성지표
모든 속성 타입approximateDistinct, exactDistinct
숫자sum, avg, min, max 및 두 distinct 지표
Date와 Timestampmin, max 및 두 distinct 지표. sum과 avg는 미지원

속성에 맞지 않는 지표는 타입 오류입니다. 배열 속성은 기본 타입만 검사하여 코드가 컴파일되더라도 런타임에서 실패할 수 있으므로 지원을 추정하지 않습니다.

$count와 두 distinct 개수는 number입니다. $count는 선택한 경우에만 반환합니다. 다른 지표는 속성의 SDK 값 타입 및 필수 여부를 따릅니다. 선택 Integer의 avg는 number | undefined, Date의 max와 Long, Decimal 및 Timestamp 지표는 문자열 기반 값일 수 있습니다. avg, min과 max는 일치 객체가 없으면 undefined입니다.

결과 키는 속성과 지표에서 정하며 TypeScript SDK에는 임의 지표 별칭이 없습니다. Python 집계의 name 인수와 다릅니다.

그룹별 모양

$groupBy 값입력$group의 해당 속성
"exact"고유 값별 그룹해당 속성의 스칼라 값
{ $fixedWidth: 10 }숫자 너비 10버킷 시작값인 숫자
{ $ranges: [[0, 3], [3, 5]] }시작 포함, 끝 제외{ startValue, endValue }
{ $duration: [10, "days"] }날짜/시각 구간버킷 시작의 ISO 문자열

범위는 양끝이 필요하여 무한히 열린 구간을 표현할 수 없습니다. Date는 YYYY-MM-DD, Timestamp는 완전한 ISO 시각을 범위 끝으로 사용합니다. 범위 그룹만 객체 형태를 반환하며 고정 너비와 날짜 그룹은 시작 스칼라를 반환합니다.

Date의 단위는 days, weeks, months, quarters와 years입니다. Timestamp에는 seconds, minutes와 hours도 있습니다. days 이하 단위는 수를 지정할 수 있고 weeks 이상은 1만 받습니다.

정확도와 한도

exact의 기본 최대 그룹 수는 10,000입니다. 고유 값이 한도를 넘으면 일부 객체가 그룹에서 제외되어 근사 결과가 될 수 있습니다. $exactWithLimit를 지원 범위 안에서 조정하거나 먼저 집합을 좁힙니다. TypeScript OSDK 집계 결과에는 원격 응답의 accuracy 필드가 노출되지 않습니다.

객체 로드의 OSv1 10,000개 제한은 개별 객체를 읽는 한도입니다. 집계는 객체를 백엔드에서 계산하며 반환 그룹 수 및 집계 복잡도 제한을 따르므로 입력 객체 개수를 같은 한도로 해석하지 않습니다.

REST 집계 API는 accuracy에 REQUIRE_ACCURATE 또는 기본 ALLOW_APPROXIMATE를 받습니다. 정확도를 요구했지만 보장할 수 없으면 AggregationAccuracyNotSupported 오류가 발생합니다. 이 REST 필드를 TSv2 aggregate의 $select/$groupBy 객체에 임의로 넣지는 않습니다.

액션 실행과 검증

가상의 addReview는 String restaurantId, Integer reviewRating과 String reviewSummary를 받습니다. 실제 실행은 온톨로지를 변경하므로 권한과 제출 조건을 충족해야 합니다.

import { Client } from "@osdk/client";
import { addReview } from "@my-app/sdk";

export function validateReview(client: Client, restaurantId: string, reviewRating: number, reviewSummary: string) {
    return client(addReview).applyAction({ restaurantId, reviewRating, reviewSummary }, { $validateOnly: true });
}

export function submitReview(client: Client, restaurantId: string, reviewRating: number, reviewSummary: string) {
    return client(addReview).applyAction({ restaurantId, reviewRating, reviewSummary }, { $returnEdits: true });
}

이 코드는 일반 앱 helper이며 함수 레지스트리의 숫자 별칭 규칙과는 별개입니다. $validateOnly는 실행하지 않고 result의 VALID/INVALID, submissionCriteria와 매개변수별 제약 결과를 반환합니다. 실제 applyAction은 검증 오류에서 예외를 던집니다. $returnEdits와 $validateOnly를 동시에 true로 둘 수 없습니다.

편집 반환의 type은 edits 또는 largeScaleEdits이며 후자를 검증 실패로 해석하면 안 됩니다. edits에는 추가 및 수정 객체, 링크와 삭제 개수 등이, editedObjectTypes에는 변경된 객체 유형 이름이 들어갑니다. 이것은 수정한 객체 데이터 자체가 아닙니다. 옵션을 지정하지 않은 실행의 반환은 undefined입니다.

배치 액션

batchApplyAction은 매개변수 객체 배열을 받습니다. 결과에는 검증 목록 없이 편집 결과가 포함됩니다. 배치의 한 액션이 실패하면 해당 배치의 온톨로지 편집은 적용하지 않는 all-or-nothing 계약입니다. 외부 시스템의 효과까지 롤백한다는 보장은 액션 일관성과 구분합니다.

import { Client } from "@osdk/client";
import { addReview } from "@my-app/sdk";

export function submitReviewBatch(client: Client, restaurantId1: string, restaurantId2: string) {
    return client(addReview).batchApplyAction([
        { restaurantId: restaurantId1, reviewRating: 5, reviewSummary: "It was great!" },
        { restaurantId: restaurantId2, reviewRating: 4, reviewSummary: "Good food but service can improve." },
    ], { $returnEdits: true });
}

평점과 문구는 가상 예제입니다. 오류를 잡아 성공으로 바꾸지 않으므로 호출한 앱이 실패를 처리해야 합니다.

함수 호출

앱에 가져온 생성 함수 정의를 client에 넘기고 executeFunction에 이름 있는 매개변수를 전달합니다. 예를 들어 findSimilarRestaurants가 restaurantId를 받아 Restaurant 집합을 반환하는 계약이라면 다음과 같습니다.

import { Client } from "@osdk/client";
import { findSimilarRestaurants } from "@my-app/sdk";

export function findSimilar(client: Client, restaurantId: string) {
    return client(findSimilarRestaurants).executeFunction({ restaurantId });
}

반환 집합에서 필요한 조회를 이어갈 수 있습니다. 함수의 일반 타입과 실제 생성 SDK가 지원하는 호출 타입을 구분합니다.

시나리오 클라이언트

온톨로지 시나리오 지원은 Experimental이며 플랫폼 인스턴스에 제공되지 않을 수 있습니다. createScenario는 플랫폼에 실제 새 시나리오를 만들며 비동기입니다. withScenario는 기존 RID를 가진 클라이언트를 구성하고 이 단계에서는 네트워크를 호출하지 않습니다.

import { Client } from "@osdk/client";
import { createScenario, withScenario } from "@osdk/client/unstable-do-not-use";
import { Restaurant } from "@my-app/sdk";

export async function createAndReadScenario(client: Client, restaurantId: string) {
    const scenario = await createScenario(client);
    return scenario(Restaurant).fetchOne(restaurantId);
}

export function readExistingScenario(client: Client, scenarioRid: string, restaurantId: string) {
    return withScenario(client, scenarioRid)(Restaurant).fetchOne(restaurantId);
}

조회와 액션은 해당 시나리오의 격리된 상태를 사용합니다. 버전 조건, 배치 미지원과 기본 온톨로지 병합은 OSDK 시나리오를 따릅니다.

1.x에서 옮기는 경우에는 TypeScript SDK 이전, 업데이트를 구독하려면 객체 집합 구독을 확인합니다.