GraphQL 집계를 사용하면 SQL GROUP BY 및 집계 함수와 유사하게 API를 통해 직접 개수, 합계, 평균 등과 같은 요약된 데이터를 검색할 수 있습니다. 클라이언트에서 모든 레코드를 가져오고 요약을 계산하는 대신 특정 필드별로 데이터를 그룹화하고 집계 값을 계산하도록 서버에 요청할 수 있습니다. 이는 단일 쿼리에서 보고서 또는 분석(예: 범주별 제품 수 또는 작성자당 평균 게시물 등급 가져오기)을 작성하는 데 유용합니다.
집계 쿼리는 그룹화된 결과를 반환합니다. 각 결과는 해당 그룹에 대한 계산된 집계 메트릭과 함께 특정 필드 값을 공유하는 레코드 그룹을 나타냅니다. 이 설명서에서는 가상의 전자 상거래 스키마와 함께 GraphQL 집계 기능을 사용하는 방법, 추출할 수 있는 데이터 형식, 예제 쿼리, 알아야 할 중요한 제한 사항 및 동작에 대해 설명합니다.
예제 스키마: 전자상거래 저장소
이 스키마에서 제품은 범주에 속합니다. 각각 Product
에는 가격 및 등급(집계할 수 있는 숫자 값) 및 (범주 필드별) 관계 Category
와 같은 필드가 있습니다.
Category
이름이 있습니다. 이 스키마를 사용하여 집계 쿼리를 보여 줍니다.
예를 들어 간소화된 GraphQL 형식은 다음과 같습니다.
type Category {
id: ID!
name: String!
products: [Product!]! # one-to-many relationship
}
type Product {
id: Int!
name: String!
price: Float!
rating: Int!
category_id: Int!
category: Category! # many-to-one relationship
}
type ProductResult { # automatically generated, adding groupBy capabilities
items: [Product!]!
endCursor: String
hasNextPage: Boolean!
groupBy(fields: [ProductScalarFields!]): [ProductGroupBy!]!
}
type Query {
products(
first: Int
after: String
filter: ProductFilterInput
orderBy: ProductOrderByInput
): ProductResult!
이 예제에서 쿼리는 products
일반 항목 목록을 반환하거나 사용되는 경우 groupBy
집계된 결과를 반환할 수 있습니다. 이 쿼리의 groupBy
와 집계 기능 사용에 집중해 보겠습니다.
집계 쿼리를 사용하는 이유는 무엇인가요?
GraphQL에서 집계 쿼리를 사용하면 수동 처리 없이 데이터에 대한 질문에 신속하게 대답할 수 있습니다. 예를 들어 다음과 같은 인사이트를 추출할 수 있습니다.
- 총 개수: 예: "각 범주에 있는 제품 수?"
- 합계 및 평균: 예: "범주당 총 수익은 무엇인가요?" 또는 "범주별 제품의 평균 등급?"
- 최소/최대값: 예: "각 범주에서 가장 높고 가장 낮은 가격 항목은 무엇인가요?"
- 고유 값: 예: "고객이 몇 개의 고유한 도시를 왔나요?" 또는 "모든 블로그 게시물에 사용되는 고유 태그 나열"
모든 레코드를 검색하고 애플리케이션에서 이러한 인사이트를 계산하는 대신 집계 쿼리를 통해 서버에서 수행할 수 있습니다. 이렇게 하면 데이터 전송이 줄어들고 그룹화 및 계산에 데이터베이스 최적화가 사용됩니다.
집계 쿼리 기본 사항
집계를 수행하려면 GraphQL 쿼리에서 인수를 groupBy
지정하여 데이터를 그룹화하는 방법을 정의하고 결과에서 집계 필드(예: 개수 또는 합계)를 요청합니다. 응답에는 그룹화된 레코드 목록이 포함되며, 각 레코드에는 그룹의 키 값과 집계된 메트릭이 포함됩니다.
예제 1: 범주별 제품 수
범주별로 제품을 그룹화하고 각 그룹에 있는 제품 수를 계산해 보겠습니다. 쿼리는 다음과 같을 수 있습니다.
query {
products {
groupBy(fields: [category_id])
{
fields {
category_id # grouped key values
}
aggregations {
count(field: id) # count of products in each group (count of "id")
}
}
}
}
이 쿼리에서:
-
groupBy(fields: [category_id])
는 패브릭 GraphQL 엔진에 필드별로category_id
제품을 그룹화하도록 지시합니다. - 결과 선택에서
group
을 요청하고id
필드에 대해count
집계를 요청합니다. 계산id
은 해당 그룹의 제품을 효과적으로 계산합니다.
결과는 다음과 같습니다 . 응답의 각 항목은 하나의 범주 그룹을 나타냅니다.
groupBy
개체에 그룹화 키가 포함되어 있습니다. 여기에 값을 count { id }
포함하고 category_id
해당 범주의 제품 수를 제공합니다.
{
"data": {
"products": {
"groupBy": [
{
"fields": {
"category_id": 1
},
"aggregations": {
"count": 3
}
},
{
"fields": {
"category_id": 2
},
"aggregations": {
"count": 2
}
},
...
]
}
}
}
이 출력은 범주 1에 3개의 제품이 있고, 범주 2에는 2가 있습니다.
예제 2: 합계 및 평균
한 쿼리에서 여러 집계 메트릭을 요청할 수 있습니다. 각 범주에 대해 모든 제품의 총 가격과 평균 등급을 원한다고 가정합니다.
query {
products {
groupBy(fields: [category_id])
{
fields {
category_id
}
aggregations {
count(field: id) # number of products in the category
sum(field: price) # sum of all product prices in the category
avg(field: rating) # average rating of products in the category
}
}
}
}
이 쿼리는 다음 결과를 반환합니다.
{
"data": {
"products": {
"groupBy": [
{
"fields": {
"category_id": 1
},
"aggregations": {
"count": 3,
"sum": 2058.98,
"avg": 4
}
},
{
"fields": {
"category_id": 2
},
"aggregations": {
"count": 2,
"sum": 109.94,
"avg": 4
}
},
...
]
}
}
}
각 그룹 개체에는 제품 수, 가격 합계 및 해당 범주의 평균 등급과 같은 범주 및 계산 집계가 포함됩니다.
예제 3: 여러 필드로 그룹화
여러 필드를 그룹화하여 다중 수준 그룹화할 수 있습니다. 예를 들어, rating
필드가 제품에 있는 경우, category_id
와 rating
로 그룹화한 다음, 그 그룹에 대해 price
의 평균을 계산할 수 있습니다.
query {
products {
groupBy(fields: [category_id, rating])
{
fields {
category_id
rating
}
aggregations {
avg(field: price)
}
}
}
}
이렇게 하면 아래와 같이 범주 와 등급의 고유한 조합으로 제품을 그룹화합니다.
{
"fields": {
"category_id": 10,
"rating": 4
},
"aggregations": {
"avg": 6.99
}
}
또한 데이터의 각 범주 등급 쌍에 대해 이 작업을 진행합니다.
예제 4: 고유 사용
집계 기능은 고유 값을 계산하거나 고려하는 고유 한정자를 지원합니다. 예를 들어 제품 컬렉션에 존재하는 고유 범주 수를 확인하려면 고유 개수를 사용할 수 있습니다.
query {
products {
groupBy(fields: [category_id])
{
fields {
category_id
}
aggregations {
count(field: id, distinct: true)
}
}
}
}
이 쿼리는 각 범주에 대한 고유 제품 수를 사용하여 결과를 반환합니다. 결과는 다음과 같습니다.
{
"data": {
"products": {
"groupBy": [
{
"fields": {
"category_id": 1
},
"aggregations": {
"count": 3
}
},
{
"fields": {
"category_id": 2
},
"aggregations": {
"count": 2
}
},
...
]
}
}
}
예제 5: 별칭 사용
집계에 대한 별칭을 만들어 집계된 결과에 대한 의미 있고 이해하기 쉬운 이름을 제공할 수 있습니다. 예를 들어 결과를 더 잘 이해하기 위해 고유한 제품 범주를 계산하기 때문에 이전 예제 distinctProductCategoryCount
의 집계 이름을 지정할 수 있습니다.
query {
products {
groupBy(fields: [category_id])
{
fields {
category_id
}
aggregations {
distinctProductCategoryCount: count(field: id, distinct: true)
}
}
}
}
결과는 유사하지만 사용자 지정 별칭과 더 의미가 있습니다.
{
"data": {
"products": {
"groupBy": [
{
"fields": {
"category_id": 1
},
"aggregations": {
"distinctProductCategoryCount": 3
}
},
{
"fields": {
"category_id": 2
},
"aggregations": {
"distinctProductCategoryCount": 2
}
},
...
]
}
}
}
예제 6: having
절 사용
절을 사용하여 집계된 결과를 필터링할 수 있습니다 having
. 예를 들어 두 개보다 큰 결과만 반환하도록 이전 예제를 수정할 수 있습니다.
query {
products {
groupBy(fields: [category_id])
{
fields {
category_id
}
aggregations {
distinctProductCategoryCount: count(field: id, distinct: true, having: {
gt: 2
})
}
}
}
}
결과는 두 개 이상의 제품이 있는 유일한 범주의 단일 값을 반환합니다.
{
"data": {
"products": {
"groupBy": [
{
"fields": {
"category_id": 1
},
"aggregations": {
"distinctProductCategoryCount": 3
}
}
]
}
}
}
사용 가능한 집계 함수
사용 가능한 정확한 함수는 구현에 따라 달라지지만 일반적인 집계 작업에는 다음이 포함됩니다.
- count – 그룹의 레코드 수(또는 필드의 null이 아닌 값)입니다.
- sum – 숫자 필드에 있는 모든 값의 합계입니다.
- avg – 숫자 필드에 있는 값의 평균(평균)입니다.
- min – 필드의 최소값입니다.
- max – 필드의 최대값입니다.
GraphQL API에서는 일반적으로 예제와 같이 함수 이름 및 대상 필드를 지정하여 요청됩니다count(field: id)
sum(field: price)
. 각 함수는 적용된 하나 이상의 필드를 선택할 수 있는 개체를 반환합니다. 예를 들어, sum(field: price)
은 그 그룹의 가격 필드 합계를 제공하고, count(field: id)
은 사실상 항목 수를 나타내는 ID의 개수를 제공합니다.
비고
현재 집계 작업(예: count
, sum
, avg
min
및)은 max
숫자 또는 정량적 필드에서만 작동합니다. 예를 들어 정수, 부동 소수점, 날짜입니다. 텍스트 필드에는 사용할 수 없습니다. 예를 들어 문자열의 "평균"을 사용할 수 없습니다. 다른 형식(예: 연결 또는 어휘 최소/최대와 같은 향후 가능한 함수에 대한 텍스트)에 대한 집계 수행에 대한 지원은 계획되어 있지만 아직 사용할 수 없습니다.
제한 사항 및 모범 사례
GraphQL에서 집계를 사용하는 경우 고려해야 할 몇 가지 중요한 규칙과 제한 사항이 있습니다. 쿼리의 유효성을 보장하고 결과가 예측 가능하도록 하며, 특히 결과 페이지를 이동할 때 이를 보장합니다.
집계 및 원시 항목은 상호 배타적입니다 . 현재는 그룹화된 요약 데이터와 동일한 쿼리에 있는 항목의 원시 목록을 동시에 검색할 수 없습니다. 컬렉션에 대한 집계 쿼리는
groupBy
일반 항목 목록 대신 그룹화된 데이터를 반환합니다. 예를 들어, 우리의 API에서는products(...)
쿼리를 사용할 때groupBy
를 사용하지 않을 경우 제품 목록을 반환하거나groupBy
를 사용할 경우 그룹화된 결과 목록을 반환하지만, 두 가지 모두 동시에 반환하지는 않습니다. 위의 집계된 예제에서는 필드 및 집계 필드group
가 표시되는 반면 일반적인items
제품 목록은 없는 것을 알 수 있습니다. 하나의 쿼리에서 그룹과 함께 일반 항목을 요청하려고 하면 GraphQL 엔진이 오류를 반환하거나 해당 선택을 허용하지 않습니다. 원시 데이터와 집계된 데이터가 모두 필요한 경우 두 개의 별도 쿼리를 실행하거나 이 제한을 해제할 수 있는 향후 업데이트를 기다려야 합니다. 이 디자인은 응답 구조를 명확하게 유지하기 위한 것이므로 쿼리는 "집계 모드" 또는 "목록 항목 모드"에 있습니다.그룹화된 결과 정렬(
orderBy
기본 키와 비교): 집계된 그룹을 가져올 때 명시적 정렬 순서를 지정하지 않으면 그룹이 반환되는 순서가 보장되지 않습니다. 특히 그룹화 키가 고유하지 않거나 명백한 기본 순서가 없는 경우 집계된 쿼리에서 인수 또는sort
인수를 사용하여orderBy
결과에서 그룹을 정렬하는 방법을 정의하는 것이 좋습니다. 예를 들어, 이름을 기준으로 그룹화하면 결과가 범주 이름의 알파벳 순서로, 가장 높은 개수 순서로, 또는 삽입된 순서로 반환되어야 하나요?orderBy
그룹이 없으면 데이터베이스에서 결정된 임의의 순서로 그룹화가 반환될 수 있습니다. 또한 제한/오프셋 또는 커서 페이지 매김을 사용하여 그룹화된 결과를 페이지 매김하려는 경우 페이지 매김이 올바르게 작동하려면 안정적인 정렬 순서가 필요합니다. 대부분의 시스템에서 기본 키가 그룹화의 일부인 경우 각 그룹을 해당 키로 자연적으로 식별할 수 있게 만들면 결과는 기본적으로 그에 따라 정렬될 수 있습니다. 그러나 groupBy 필드에 기본 키가 없는 경우 일관된 순서를 얻기 위해 절을 지정orderBy
해야 합니다.고유 집계 사용: 집계에서 중복 값을 무시해야 하는 경우 고유 한정자를 사용해야 합니다. 예를 들어
count(field: category_id, distinct: true)
고유한 범주를 계산합니다. 이 방법은 이 그룹에 있는 고유 X의 수를 알고 싶은 경우에 유용합니다. 합계 또는 평균에 고유 값을 적용할 수도 있습니다. 예를 들어sum (field: price, distinct: true)
각 고유 가격 값은 그룹당 한 번만 추가됩니다. 이 경우는 덜 일반적이지만 완전성을 위해 사용할 수 있습니다. 중복 데이터가 데이터를 왜곡하는 시나리오에서 고유 집계를 사용합니다. 예를 들어 제품이 조인을 통해 여러 번 나타날 수 있는 경우 고유 개수는 한 번만 계산됩니다.
이러한 제한 사항과 지침을 염두에 두면 강력한 인사이트를 얻을 수 있는 효과적인 GraphQL 집계 쿼리를 빌드할 수 있습니다. 집계 기능은 보고 및 분석 사용 사례에 유용하지만 쿼리를 신중하게 구조화해야 합니다. 항상 groupBy
필드가 선택한 출력 필드와 일치하는지 철저히 확인하고, 특히 페이지 매김 시 예측 가능한 순서를 위해 정렬을 추가하며, 데이터 유형에 적합하게 고유 함수와 집계 함수를 적절하게 사용하세요.