Databases
OpenSearch 기반의 고성능 문서 데이터베이스입니다. 스키마 정의, CRUD, 전문 검색, 벡터 검색을 지원합니다.
주요 기능
- 스키마 정의: 필드 타입, 인덱싱 옵션, 벡터 필드 설정
- CRUD 작업: 단일/대량 문서 생성, 조회, 수정, 삭제
- 전문 검색: OpenSearch Query DSL 지원 (match, term, bool, range)
- 벡터 검색: k-NN 기반 시맨틱 검색 (Pro 플랜 이상)
- 집계: terms, date_histogram, 통계 집계
크레딧 비용
데이터베이스 작업은 유형에 따라 크레딧이 차감됩니다. 작업 실패 시 크레딧은 자동 환불됩니다.
| 작업 | 엔드포인트 | 크레딧 |
|---|---|---|
| 문서 생성 | POST /documents | 0.1 |
| 문서 조회 | GET /documents/{id} | 0.05 |
| 문서 수정 | PUT, PATCH /documents/{id} | 0.1 |
| 문서 삭제 | DELETE /documents/{id} | 0.05 |
| 대량 생성 | POST /documents/_bulk | 5.0 / 100건 |
| 대량 삭제 | POST /documents/_bulk_delete | 0.05 / 건 |
| 대량 수정 | POST /documents/_bulk_update | 0.1 / 건 |
| 전문 검색 | POST /search | 0.5 |
| 집계 | POST /aggregate | 1.0 |
| 벡터 검색 | POST /search/vector | 2.0 |
무료: 데이터베이스 생성/삭제, 목록 조회, 스키마 변경, 통계 조회, 문서 목록 조회, 문서 수 조회(_count)는 크레딧이 차감되지 않습니다.
플랜별 제한
구독 플랜에 따라 데이터베이스 리소스 제한이 다릅니다.
| 항목 | Free | Pro | Team | Enterprise |
|---|---|---|---|---|
| 최대 데이터베이스 수 | 1 | 5 | 20 | 1,000 |
| DB당 최대 문서 수 | 10,000 | 500,000 | 5,000,000 | 100,000,000 |
| 최대 스토리지 | 100 MB | 5 GB | 50 GB | 500 GB |
| 최대 문서 크기 | 100 KB | 1 MB | 10 MB | 100 MB |
| 벌크 작업 최대 건수 | 100 | 1,000 | 10,000 | 100,000 |
| 벡터 검색 | - | 1,536차원 | 2,048차원 | 4,096차원 |
데이터베이스 생성
스키마와 함께 새 데이터베이스를 생성합니다. 데이터베이스 이름은 팀 내에서 고유해야 합니다.
이름 규칙
- 소문자 영문으로 시작해야 합니다
- 소문자 영문, 숫자, 하이픈(
-), 언더스코어(_)만 사용 가능 - 3~50자 이내
aiapi_,db_system_,_로 시작할 수 없음 (예약 접두사)
curl -X POST https://api.core.today/v1/databases \
-H "X-API-Key: cdt_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "products",
"display_name": "Product Catalog",
"description": "E-commerce product database",
"schema_fields": {
"title": {"type": "text", "index": true},
"description": {"type": "text", "index": true},
"price": {"type": "float"},
"category": {"type": "keyword"},
"tags": {"type": "keyword"},
"in_stock": {"type": "boolean"},
"created_at": {"type": "date"}
}
}'응답 예시
{
"database_uid": "db_abc123",
"name": "products",
"display_name": "Product Catalog",
"description": "E-commerce product database",
"team_id": "team_xyz",
"schema_fields": {...},
"document_count": 0,
"created_at": "2024-12-26T10:00:00Z"
}지원 필드 타입
| 타입 | 설명 | 예시 |
|---|---|---|
text | 전문 검색이 가능한 텍스트 | "Product description..." |
keyword | 정확한 매칭용 문자열 (필터, 집계) | "electronics" |
integer | 정수 | 42 |
long | 64비트 정수 | 9223372036854775807 |
float | 32비트 부동 소수점 | 19.99 |
double | 64비트 부동 소수점 | 3.141592653589793 |
boolean | true/false | true |
date | ISO 8601 날짜 | "2024-12-26T10:00:00Z" |
object | 중첩 객체 (인덱싱 on/off 가능) | {"key": "value"} |
nested | 독립적으로 쿼리 가능한 객체 배열 | [{"name": "A"}, ...] |
knn_vector | 벡터 검색용 임베딩 (Pro+) | [0.1, 0.2, ...] |
벡터 필드 설정
벡터 검색을 위한 필드는 dimension과 space_type을 지정해야 합니다:
"embedding": {
"type": "knn_vector",
"dimension": 1536,
"space_type": "cosinesimil"
}문서 CRUD
자동 메타데이터 (_meta)
모든 문서에는 _meta 필드가 자동으로 추가됩니다:
_meta.created_at— 문서 생성 시각 (ISO 8601)_meta.updated_at— 마지막 수정 시각 (ISO 8601)_meta.created_by_api_key— 생성에 사용된 API 키 UID
문서 생성
# 단일 문서 생성
curl -X POST https://api.core.today/v1/databases/{database_uid}/documents \
-H "X-API-Key: cdt_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"id": "product-001",
"data": {
"title": "Wireless Headphones",
"description": "High-quality wireless headphones with noise cancellation",
"price": 199.99,
"category": "electronics",
"tags": ["audio", "wireless", "premium"],
"in_stock": true
}
}'대량 문서 생성
curl -X POST https://api.core.today/v1/databases/{database_uid}/documents/_bulk \
-H "X-API-Key: cdt_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"documents": [
{"id": "product-001", "data": {"title": "Product 1", "price": 99.99}},
{"id": "product-002", "data": {"title": "Product 2", "price": 149.99}},
{"id": "product-003", "data": {"title": "Product 3", "price": 199.99}}
]
}'응답: 성공/실패 개수와 에러 상세 정보가 반환됩니다.
문서 조회
# 특정 문서 조회
curl https://api.core.today/v1/databases/{database_uid}/documents/{doc_id} \
-H "X-API-Key: cdt_your_api_key"
# 특정 필드만 조회 (Field Projection)
curl "https://api.core.today/v1/databases/{database_uid}/documents/{doc_id}?_source=title,price" \
-H "X-API-Key: cdt_your_api_key"
# 문서 목록 조회 (페이지네이션)
curl "https://api.core.today/v1/databases/{database_uid}/documents?size=20&from=0" \
-H "X-API-Key: cdt_your_api_key"
# 문서 목록 - 특정 필드만 조회
curl "https://api.core.today/v1/databases/{database_uid}/documents?size=20&_source=title,price" \
-H "X-API-Key: cdt_your_api_key"_source: 쉼표로 구분된 필드 목록을 지정하면 해당 필드만 응답에 포함됩니다. 생략하면 모든 필드를 반환합니다.
문서 수정
# 전체 교체 (PUT)
curl -X PUT https://api.core.today/v1/databases/{database_uid}/documents/{doc_id} \
-H "X-API-Key: cdt_your_api_key" \
-H "Content-Type: application/json" \
-d '{"data": {"title": "Updated Title", "price": 299.99, ...}}'
# 부분 수정 (PATCH)
curl -X PATCH https://api.core.today/v1/databases/{database_uid}/documents/{doc_id} \
-H "X-API-Key: cdt_your_api_key" \
-H "Content-Type: application/json" \
-d '{"data": {"price": 179.99}}'문서 삭제
curl -X DELETE https://api.core.today/v1/databases/{database_uid}/documents/{doc_id} \
-H "X-API-Key: cdt_your_api_key"대량 삭제
curl -X POST https://api.core.today/v1/databases/{database_uid}/documents/_bulk_delete \
-H "X-API-Key: cdt_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"ids": ["product-001", "product-002", "product-003"]
}'크레딧: 0.05 × 문서 수. 존재하지 않는 ID는 에러로 보고됩니다.
대량 수정
curl -X POST https://api.core.today/v1/databases/{database_uid}/documents/_bulk_update \
-H "X-API-Key: cdt_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"documents": [
{"id": "product-001", "data": {"price": 179.99, "in_stock": false}},
{"id": "product-002", "data": {"price": 129.99}},
{"id": "product-003", "data": {"category": "accessories"}}
]
}'크레딧: 0.1 × 문서 수. 부분 수정(PATCH)으로 동작하며 지정된 필드만 업데이트됩니다.
문서 수 조회
# 전체 문서 수
curl https://api.core.today/v1/databases/{database_uid}/documents/_count \
-H "X-API-Key: cdt_your_api_key"
# 조건부 문서 수 (query 파라미터로 JSON 전달)
curl "https://api.core.today/v1/databases/{database_uid}/documents/_count?q=%7B%22term%22%3A%7B%22category%22%3A%22electronics%22%7D%7D" \
-H "X-API-Key: cdt_your_api_key"무료: 크레딧이 차감되지 않습니다. 응답: {"count": 1234}
필드 제외 (_source_excludes)
응답에서 특정 필드를 제외할 수 있습니다. _source와 함께 사용하면 includes/excludes로 변환됩니다.
# GET 요청 - 쿼리 파라미터로 사용
curl "https://api.core.today/v1/databases/{database_uid}/documents?_source_excludes=embedding,raw_html" \
-H "X-API-Key: cdt_your_api_key"
# POST (search) - body에 포함
curl -X POST https://api.core.today/v1/databases/{database_uid}/search \
-H "X-API-Key: cdt_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"query": {"match_all": {}},
"_source": ["title", "price"],
"_source_excludes": ["embedding"]
}'검색
OpenSearch Query DSL을 사용한 강력한 검색 기능을 제공합니다.
전문 검색 (Full-text)
curl -X POST https://api.core.today/v1/databases/{database_uid}/search \
-H "X-API-Key: cdt_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"query": {
"match": {
"description": "wireless headphones"
}
},
"size": 10,
"from": 0,
"_source": ["title", "price", "category"]
}'_source: 응답에 포함할 필드 목록입니다. 생략하면 모든 필드를 반환합니다.
복합 검색 (Boolean Query)
{
"query": {
"bool": {
"must": [
{"match": {"description": "headphones"}}
],
"filter": [
{"term": {"category": "electronics"}},
{"range": {"price": {"gte": 100, "lte": 300}}}
],
"should": [
{"term": {"in_stock": true}}
]
}
},
"sort": [
{"price": {"order": "asc"}}
],
"highlight": {
"fields": {"description": {}}
}
}Deep Pagination (search_after)
from + size가 10,000을 초과하면 search_after를 사용해야 합니다. 이전 결과의 마지막 sort 값을 전달하여 다음 페이지를 조회합니다.
{
"query": {"match_all": {}},
"sort": [
{"_meta.created_at": {"order": "desc"}},
{"_id": {"order": "asc"}}
],
"size": 100,
"search_after": ["2025-01-01T00:00:00Z", "product-500"]
}주의: search_after 사용 시 반드시 sort를 지정해야 하며, tie-breaker로 _id를 포함하는 것을 권장합니다.
검색 응답 예시
{
"total": 42,
"hits": [
{
"id": "product-001",
"score": 1.5,
"data": {
"title": "Wireless Headphones",
"price": 199.99,
...
},
"highlight": {
"description": ["High-quality <em>wireless</em> <em>headphones</em>..."]
}
}
]
}벡터 검색 (k-NN)
Pro+임베딩 벡터를 사용한 시맨틱 유사도 검색입니다. AI 모델로 생성한 텍스트/이미지 임베딩을 저장하고 검색할 수 있습니다.
벡터 필드가 있는 스키마
{
"name": "articles",
"schema_fields": {
"title": {"type": "text"},
"content": {"type": "text"},
"embedding": {
"type": "knn_vector",
"dimension": 1536,
"space_type": "cosinesimil"
}
}
}벡터 검색 요청
curl -X POST https://api.core.today/v1/databases/{database_uid}/search/vector \
-H "X-API-Key: cdt_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"field": "embedding",
"vector": [0.1, 0.2, 0.3, ...],
"k": 10,
"filter": {
"term": {"category": "technology"}
},
"_source": ["title", "content"]
}'임베딩 생성 팁
OpenAI의 text-embedding-3-small (1536차원) 또는 Cohere의 임베딩 모델을 사용하여 텍스트를 벡터로 변환할 수 있습니다. LLM API를 통해 임베딩을 생성하고 데이터베이스에 저장하세요.
집계 (Aggregations)
데이터 분석을 위한 집계 기능을 제공합니다.
curl -X POST https://api.core.today/v1/databases/{database_uid}/aggregate \
-H "X-API-Key: cdt_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"query": {"match_all": {}},
"aggregations": {
"by_category": {
"terms": {"field": "category", "size": 10}
},
"avg_price": {
"avg": {"field": "price"}
},
"price_ranges": {
"range": {
"field": "price",
"ranges": [
{"to": 100},
{"from": 100, "to": 200},
{"from": 200}
]
}
}
}
}'집계 응답 예시
{
"total": 1000,
"aggregations": {
"by_category": {
"buckets": [
{"key": "electronics", "doc_count": 350},
{"key": "clothing", "doc_count": 280},
...
]
},
"avg_price": {"value": 149.99},
"price_ranges": {
"buckets": [
{"key": "*-100.0", "doc_count": 200},
{"key": "100.0-200.0", "doc_count": 500},
{"key": "200.0-*", "doc_count": 300}
]
}
}
}데이터베이스 관리
데이터베이스 목록
curl https://api.core.today/v1/databases \
-H "X-API-Key: cdt_your_api_key"필드 추가
기존 데이터베이스에 새 필드를 추가할 수 있습니다. 기존 필드의 타입은 변경할 수 없습니다.
curl -X POST https://api.core.today/v1/databases/{database_uid}/fields \
-H "X-API-Key: cdt_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"fields": {
"rating": {"type": "float"},
"reviews_count": {"type": "integer"}
}
}'통계 조회
curl https://api.core.today/v1/databases/{database_uid}/stats \
-H "X-API-Key: cdt_your_api_key"데이터베이스 삭제
주의: 데이터베이스 삭제는 되돌릴 수 없습니다. 모든 문서가 영구 삭제됩니다.
curl -X DELETE https://api.core.today/v1/databases/{database_uid} \
-H "X-API-Key: cdt_your_api_key"필드값 자동완성 (Suggest)
keyword 타입 필드의 값을 자동완성으로 조회합니다.
curl "https://api.core.today/v1/databases/{database_uid}/suggest?field=category&prefix=ele&limit=10" \
-H "X-API-Key: cdt_your_api_key"
# 응답: {"suggestions": ["electronics", "electric-vehicles", ...]}무료: 크레딧이 차감되지 않습니다.
쿼리 저장
자주 사용하는 검색 쿼리를 저장하고 관리할 수 있습니다. 모두 무료입니다.
# 쿼리 저장
curl -X POST https://api.core.today/v1/databases/{database_uid}/queries \
-H "X-API-Key: cdt_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "할인 상품 검색",
"description": "100원 미만 전자제품",
"query": {
"bool": {
"filter": [
{"term": {"category": "electronics"}},
{"range": {"price": {"lt": 100}}}
]
}
}
}'
# 저장된 쿼리 목록
curl https://api.core.today/v1/databases/{database_uid}/queries \
-H "X-API-Key: cdt_your_api_key"
# 저장된 쿼리 삭제
curl -X DELETE https://api.core.today/v1/databases/{database_uid}/queries/{query_uid} \
-H "X-API-Key: cdt_your_api_key"SDK 예제
JavaScript / TypeScript
import axios from 'axios';
const api = axios.create({
baseURL: 'https://api.core.today/v1',
headers: { 'X-API-Key': 'cdt_your_api_key' }
});
// 문서 생성
const doc = await api.post('/databases/db_abc123/documents', {
id: 'product-001',
data: { title: 'My Product', price: 99.99 }
});
// 검색
const results = await api.post('/databases/db_abc123/search', {
query: { match: { title: 'product' } },
size: 10
});
console.log(results.data.hits);Python
import requests
API_KEY = "cdt_your_api_key"
BASE_URL = "https://api.core.today/v1"
headers = {"X-API-Key": API_KEY}
# 문서 생성
response = requests.post(
f"{BASE_URL}/databases/db_abc123/documents",
headers=headers,
json={
"id": "product-001",
"data": {"title": "My Product", "price": 99.99}
}
)
# 검색
results = requests.post(
f"{BASE_URL}/databases/db_abc123/search",
headers=headers,
json={
"query": {"match": {"title": "product"}},
"size": 10
}
)
for hit in results.json()["hits"]:
print(hit["data"]["title"])에러 응답
요청 실패 시 다음과 같은 에러 응답이 반환됩니다. 크레딧이 차감된 작업이 실패하면 자동으로 환불됩니다.
402 — 크레딧 부족
{
"detail": "Insufficient credits. Required: 0.50, Available: 0.12"
}404 — 데이터베이스 또는 문서 없음
{
"detail": "Database not found"
}
// 또는
{
"detail": "Document not found"
}400 — 유효성 검증 실패
{
"detail": "Database with name 'products' already exists"
}
// 또는
{
"detail": "Invalid query: Query type 'script' is not allowed"
}
// 또는
{
"detail": "Pagination limit exceeded: from (9990) + size (20) = 10010 exceeds maximum of 10000. Use search_after for deep pagination."
}403 — 플랜 제한
{
"detail": "Vector search is not available in your plan"
}
// 또는
{
"detail": "Maximum number of databases (1) reached for your plan"
}Best Practices
- 스키마 설계: 검색에 자주 사용되는 필드는
keyword타입으로, 전문 검색이 필요한 필드는text타입으로 지정하세요. - 대량 작업: 여러 문서를 처리할 때는
/_bulk엔드포인트를 사용하세요. - 페이지네이션:
from + size는 최대 10,000까지 가능합니다. 그 이상은search_after와sort를 함께 사용하세요. - 필터 vs 쿼리: 정확한 값 매칭은
filter에, 점수 계산이 필요한 검색은query에 작성하세요. - 벡터 검색: 벡터 차원은 임베딩 모델에 맞게 설정하고, 필터와 함께 사용하면 더 효율적입니다.