https://www.sanity.io/docs/how-queries-work#8ca3cefc3a31
GROQ (Graph-Relational Object Queries) 쿼리 언어의 아이디어는 애플리케이션이 필요로 하는 정확한 정보를 설명하고, 여러 문서 집합에서 정보를 결합하여 필요한 정확한 필드만 포함된 응답을 생성할 수 있는 것입니다.
프론트엔드에서 이러한 쿼리를 수행하기 위해 클라이언트를 설정하는 데 도움이 필요하다면, JavaScript
또는 PHP용 클라이언트 문서를 확인해보세요. 또한 GROQ Arcade를 방문하여 JSON 소스를 쿼리하고 이 언어에 익숙해질 수도 있습니다.
기본 사항부터 시작해봅시다. 이 간단한 쿼리를 살펴보고 세부 사항을 분석해보겠습니다:
*[_type == 'movie' && releaseYear >= 1979]
일반적으로 쿼리는 *로 시작합니다. 이 별표는 데이터셋의 모든 문서를 나타냅니다. 유용한 작업을 수행하기 위해 일반적으로 이어서 대괄호 내의 필터가 옵니다. 위의 필터는 두 개의 조건으로 구성되어 있습니다:
첫 번째로 문서 유형으로 필터링합니다. Sanity의 모든 문서는 유형을 가져야 하며, 유형은 항상 _type
필드에 있습니다. (Sanity에서는 Sanity 고유의 필드를 필드 이름과 충돌하지 않도록 _
로 접두사를 붙입니다.) 따라서 _type == 'movie'
는 이 쿼리를 'movie'
유형의 문서로 제한합니다. &&
는 "그리고" 연산자입니다.
두 번째 조건인 releaseYear >= 1979
는 영화에 releaseYear
라는 숫자를 포함한다고 가정합니다. 이 숫자가 1979
보다 크거나 같은 문서와 일치합니다.
따라서 이 쿼리를 실행하면 데이터셋에서 1979년 이후의 모든 영화를 포함하는 배열이 결과로 반환됩니다. 멋지군요! 그러나 일반적인 애플리케이션에서 영화는 배우, 스태프, 포스터, 태그 라인, 상영 시간, 평점 등 많은 정보를 포함하는 거대한 문서일 수 있습니다. 개요에서 영화 목록을 렌더링하는 것이 목표라면 대역폭을 낭비하게 됩니다. 이때 프로젝션을 사용할 수 있습니다.
일반적인 프로젝션은 중괄호로 둘러싸여 각 영화에 대해 표시하려는 데이터를 설명합니다. 이 쿼리에서 _id
, title
및 releaseYear
를 사용하여 각 영화에 대한 식별자, 제목 및 출시 연도를 얻는 간단하고 명확한 프로젝션을 작성할 수 있습니다. 다음과 같을 수 있습니다: {_id, title, releaseYear}
. 모두 함께 사용하면 다음과 같습니다:
*[_type == 'movie' && releaseYear >= 1979]{ _id, title, releaseYear }
이제 다른 문제가 있습니다. 영화가 정해진 순서로 나타나지 않습니다. 예를 들어 우리는 영화를 연도별로 정렬하고 싶을 수 있습니다. 이를 위해 order
함수를 사용합니다. order
함수는 필드 목록과 정렬 방향을 지정하여 문서를 해당 방식으로 정렬합니다. releaseYear
를 기준으로 영화를 정렬하고 싶다면 order(releaseYear)
를 사용할 수 있습니다. 다음과 같습니다:
*[_type == 'movie' && releaseYear >= 1979] | order(releaseYear) {
_id, title, releaseYear
}
(여기서 order()
함수 앞에 |
연산자가 필요합니다. 나중에 더 자세히 설명하겠습니다.)
GROQ 문을 데이터 흐름으로 생각합니다. 먼저 모든 것(*
)이 [_type == 'movie' && ...]
필터를 통과한 다음, 해당 영화가 order()
함수를 통해 정렬되고, 그 결과로 projection {_id, title, ...}
이 매핑되어 반환됩니다.
order
함수는 필드 목록을 받으며, 필요에 따라 각 필드에 대한 정렬 방향을 지정할 수 있습니다. 예를 들어 영화를 연도별로 정렬하고, 각 연도 내에서는 제목별로 알파벳순으로 정렬하려면 다음과 같은 정렬을 사용할 수 있습니다: order(releaseYear, title)
. 가장 최신 영화를 먼저 표시하려면 다음과 같이 정렬 방향을 반대로 지정할 수 있습니다: order(releaseYear desc, title)
.
팁:
asc
는 "오름차순",desc
는 "내림차순"을 의미합니다. 정렬 방향을 지정하지 않으면 Sanity는 오름차순으로 정렬하는 것으로 간주합니다.
마지막으로 이 쿼리에 대한 마지막 문제가 있습니다. 세계에는 수많은 영화가 있습니다. 데이터셋에는 수만 개의 영화가 포함될 수 있습니다. 표시할 목록의 일부를 설명하는 방법이 필요합니다. 이는 선택자를 사용하여 수행됩니다. 첫 번째 영화만 원한다면 [0]
을 추가할 수 있습니다. 이는 배열 접근자와 정확히 동일하게 작동하며 첫 번째 요소만 반환합니다. 범위 연산자를 사용하여 슬라이스를 가져올 수도 있습니다. 예를 들어 [0...100]
은 0부터 99까지의 인덱스를 통해 첫 100개의 영화를 반환합니다. [1023...1048]
또는 다른 원하는 슬라이스를 요청할 수도 있습니다. 따라서 다음과 같이 설명할 수 있습니다. 쿼리는 다음과 같습니다:
*[_type == 'movie' && releaseYear >= 1979] | order(releaseYear) {
_id, title, releaseYear
}[0...100]
Sanity에서 참조(reference)는 한 문서에서 다른 문서로의 링크입니다. 표준 참조는 "강한"(hard) 참조로서, 문서가 다른 문서를 참조할 때 대상 문서가 존재해야 하며 참조가 제거될 때까지 실제로 삭제되지 않도록 방지됩니다. (참조된 문서를 삭제할 수 없습니다.) (참조 대상을 유지하지 않는 "약한 참조(weak reference)"도 있습니다. _weak
키를 참조 개체에 추가하여 만들 수 있습니다. 예를 들어 {_ref: "<문서 ID>", _weak: true}
와 같이 작성하면 됩니다.)
간단하게 생각해서 "person"
타입의 문서가 다음과 같다고 가정해봅시다:
{
_id: "ridley-scott",
_type: "person",
name: "Ridley Scott"
}
간단하게 유지하기 위해, 아래와 같이 각 영화에는 참조로서 "director"
라는 필드가 있을 수 있습니다:
{
_id: "alien",
_type: "movie",
title: "Alien",
releaseYear: 1979,
director: { _ref: "ridley-scott" }
}
Sanity 고유의 필드는 밑줄로 시작하며, 문서 내에서 _ref
키를 포함하는 객체는 강한 참조가 됩니다.
이제 이 참조를 사용하여 유용한 작업을 수행할 수 있습니다. 가장 기본적인 작업은 참조를 확장하는 것입니다. 이전에 살펴본 영화 쿼리를 다시 살펴보겠습니다.
*[_type == 'movie' && releaseYear >= 1979]{
_id, title, releaseYear
}
반환된 결과에 감독을 포함하려는 경우, 우리가 아는 것이 없다면 다음과 같이 시도할 수 있습니다:
*[_type == 'movie' && releaseYear >= 1979]{
_id, title, releaseYear,
director
}
그러나 간단히 감독을 포함한다고하면, 실제로는 문서의 director
필드에 있는 내용이 반환되어 참조 설명의 문자 그대로가 됩니다:
[
{
_id: "alien",
title: "Alien",
releaseYear: "1979",
director: {
_ref: "ridley-scott"
}
},
… (다른 영화)
]
이는 우리가 원하는 것이 아니며, 해당 참조를 따라가고 싶습니다! 참조를 따라가도록 Sanity에 지시하기 위해 dereferencing
연산자 ->
를 추가합니다:
*[_type == 'movie' && releaseYear >= 1979]{
_id, title, releaseYear,
director->
}
이제 유용합니다. 다음과 같은 결과를 얻게됩니다:
[
{
_id: "alien",
title: "Alien",
releaseYear: "1979",
director: {
_id: "ridley-scott",
_type: "person",
name: "Ridley Scott"
}
},
… (다른 영화)
]
그런 다음 감독에 대한 메타데이터를 모두 제거하고 싶을 수도 있습니다. 감독에 대한 별도의 프로젝션을 추가할 수 있습니다:
*[_type == 'movie' && releaseYear >= 1979]{
_id, title, releaseYear,
director->{name}
}
쿼리는 이제 우리가 원하는 대로 이름 속성만 포함된 감독을 반환합니다:
{
_id: "alien",
title: "Alien",
releaseYear: "1979",
director: {
name: "Ridley Scott"
}
}
하지만 더 나은 방법이 있습니다. 프로젝션에서 기존 문서의 기존 필드에 제한되지 않고, 실제로 새 필드를 선언할 수도 있습니다. 예를 들어 우리가 간결한 영화 목록을 작성하고 제목, 연도 및 감독 이름만 원한다고 가정해봅시다. 우리는 이름을 추출하고 새 필드에 넣어 다음과 같이 수행할 수 있습니다:
*[_type == 'movie' && releaseYear >= 1979]{
_id, title, releaseYear,
"directorName": director->name
}
이제 쿼리는 우리가 원하는 대로 원하는 형식으로 반환됩니다:
{
_id: "alien",
title: "Alien",
releaseYear: "1979",
directorName: "Ridley Scott"
}
위의 예제는 참조를 확장하는 방법을 보여주지만, 때로는 참조 배열을 다룰 때도 있습니다. 위의 예제에서 우리는 프로듀서를 추가하고 싶다고 가정해봅시다. 스키마에서 이를 설정하는 방법에 대한 자세한 내용은 배열 문서에서 찾을 수 있지만, 데이터를 쿼리하는 방법에 대해 고려해보겠습니다.
이 수정된 예제에서 다음과 같은 쿼리를 살펴보겠습니다:
*[_type == 'movie' && releaseYear >= 1979]{
_id, title, releaseYear, director,
producers[]
}
producers
뒤에 대괄호를 사용했는데, 이는 배열임을 나타냅니다. producers
뒤에 s
를 사용한 것에 유의하세요. 스키마의 명명 규칙은 GROQ에 영향을 주지 않습니다(올바른 이름만 사용하면 됩니다). 배열에는 복수형 형태를 사용하는 것을 권장합니다.
이제 다음과 같은 결과를 얻을 수 있습니다:
[
{
_id: "alien",
title: "Alien",
releaseYear: "1979",
director: {
_ref: "ridley-scott"
}
producers: [
{
_key: "<uniqueKey1>",
_type: "reference",
_ref: "gordon-carroll"
},
{
_key: "<uniqueKey2>",
_type: "reference",
_ref: "david-giler"
},
{
_key: "<uniqueKey3>",
_type: "reference",
_ref: "walter-hill"
},
]
},
… (다른 영화)
]
이전과 마찬가지로 각 프로듀서에 대한 세부 정보가 반환되지 않습니다. 우리는 참조 확장을 위해 다시 한 번 참조 해체 연산자 (->
)를 사용할 것입니다. 그러나 배열을 탐색하기 위해 대괄호는 필수입니다.
*[_type == 'movie' && releaseYear >= 1979]{
_id, title, releaseYear, director,
producers[]->
}
이제 참조 배열의 각 프로듀서에 대한 전체 세부 정보가 반환됩니다. 단일 참조와 마찬가지로 프로젝션 및 노출 프로젝션을 사용할 수 있습니다(프로젝션은 참조 연산자 뒤에 위치해야 함).
주의:
대괄호를 잊어버려 참조 배열을 확장하는 것을 잊을 수 있습니다(즉,producers->
대신producers[]->
를 쿼리하는 경우 전체 값이null
인 단일 값이 반환됩니다).GROQ
탐색의 특성상 이것은 어려울 수 있습니다.
참조를 다룰 때 references()
라는 유용한 함수가 있습니다. 이 함수를 사용하여 특정 다른 문서를 참조하는 문서만 선택하는 필터로 사용할 수 있습니다. 예를 들어 Ridley Scott
가 참여한 모든 영화를 나열하려면 다음과 같습니다:
*[_type == 'movie' && references('ridley-scott')]
첫 번째 실제 조인을 작성해 보겠습니다: 사람들의 목록을 작성하고 그들이 참여한 모든 영화를 포함하고 싶다고 가정해봅시다. "person"
타입의 문서를 쿼리하지만 각 사람의 프로젝션에서는 그들이 참여한 영화를 요청합니다. 이를 위해 부모 연산자 ^
를 간단히 소개하겠습니다. 먼저 쿼리를 살펴보겠습니다:
*[_type == "person"]{
_id, name,
"movies": *[_type == "movie" && references(^._id)].title
}
조인에서 부모 연산자는 "부모" 문서를 참조하는 방법입니다. 이 예에서 "person"
타입 문서에 대한 외부 쿼리는 일련의 사람들을 가져오고 각 사람에 대해 _id
와 name
을 반환합니다. 그런 다음 해당 사람을 참조하는 영화를 가져오고자합니다.
이제 새로운 "movies"
필드를 선언하여 "movie"
타입 문서에 대한 새 쿼리를 시작합니다. 그러나 각 사람마다 영화 쿼리를 해당 사람을 참조하는 영화로 제한하려고 합니다. 이를 위해 사람의 _id
가 필요하지만 영화 쿼리에서 _id
를 작성하면 영화의 _id
를 참조합니다.
사람 레코드의 필드로 이동하기 위해 부모 레벨을 "위로" 이동하는 부모 연산자 ^
를 사용합니다. 따라서 ^
는 영화 쿼리에 대해 특정 "person"
문서를 참조하며, ^._id
는 해당 사람의 _id
이며, ^.name
은 해당 사람의 이름입니다. 따라서 위의 쿼리에서 references(^._id)
라고 말할 때, 현재 사람을 참조하는 영화로 영화를 제한합니다.
이 쿼리에서 아직 이야기하지 않은 새로운 것이 하나 더 있습니다. 영화 하위 쿼리를 다음과 같이 작성할 수도 있습니다:
*[_type == "movie" && references(^._id)]{title}
영화 목록은 다음과 같을 것입니다:
"movies": [{title: "Alien"}, {title: "Blade Runner"}, …]
제목만 원하기 때문에 "노출 프로젝션(naked projection)"을 사용할 수 있습니다. 원하는 필드를 이름으로 지정하면 다음과 같이 값의 간단한 배열을 얻을 수 있습니다:
"movies": [“Alien”, “Blade Runner”, …]
따라서 완전성을 위해 위의 전체 사람 w/movies
쿼리의 결과는 다음과 같을 수 있습니다:
[
{
_id: "river-phoenix",
name: "River Phoenix",
movies: ["My Own Private Idaho", "Stand By Me", …]
},
{
_id: "ridley-scott",
name: "Ridley Scott",
movies: ["Alien", "Blade Runner", …]
},
…
]
Sanity는 문서를 필터링하기 위해 점점 더 많은 방법을 지원합니다. 우리는 _type == 'movie'
와 releaseYear >= 1979
와 같은 간단한 속성 비교를 보여주었습니다. references()
함수를 사용하여 참조에 의한 필터링을 보여주었습니다. 추가로 다음과 같은 기능을 지원합니다:
match
연산자를 사용한 텍스트 검색, 예: *[title match "Alien*"]
*[defined(status)]
, status 속성이 설정된 문서에만 일치하는 문서를 선택합니다.in
연산자, 예: *["sci-fi" in genres]
, genres가 배열이고 해당 배열이 "sci-fi" 값을 포함하는 모든 문서와 일치합니다.&&
(그리고), ||
(또는), !
(부정)과 결합할 수 있습니다. 예를 들어 *[_type == "movie" && (!("sci-fi" in genres) || releaseYear >= 1979)]
와 같이 사용할 수 있습니다.GROQ에서 유용한 점은 필터링과 프로젝션을 프로젝션 내부에서도 사용할 수 있다는 것입니다. 예를 들어, 건축가를 위한 작업을하는 경우 각 프로젝트에는 여러 개의 이정표가 있습니다. 문서는 다음과 같을 수 있습니다:
{
_id: "timmerhuis"
_type: "project",
title: "Timmerhuis",
milestones: [
{status: "competition", year: 2009},
{status: "design-development", year: 2011},
{status: "breaking-ground", year: 2013},
{status: "completed", year: 2015}
]
}
그리고 우리가 생성하려는 보기는 프로젝트의 현재 상태를 보여주는 것입니다. 이를 위해 가장 최신 이정표를 찾고 해당 상태 태그를 추출할 수 있습니다. 이를 GROQ로 다음과 같이 수행할 수 있습니다:
*[_type == "project"]{
_id, title,
"status": milestones|order(year desc)[0].status
}
status
쿼리인 milestones|order(year desc)[0].status
를 자세히 살펴보겠습니다:
먼저, 우리는 프로젝트에 포함된 (순서가 지정되지 않은 경우도 있음) 이정표 목록을 가져오기 위해 milestones
필드를 사용합니다. |
파이프 연산자를 사용하여이 배열의 내용을 year
를 기준으로 내림차순으로 정렬하는 order
함수에 보냅니다. 그런 다음 첫 번째 요소 [0]
(가장 최신 이정표) 만 선택하고 해당 상태 필드의 값을 반환합니다. 따라서 이제 우리의 프로젝트 목록은 다음과 같이 될 것입니다:
[
{
_id: "timmerhuis",
title: "Timmerhuis",
status: "completed"
},
…
]
또 다른 멋진 기능을 시도해보겠습니다. 이 객체의 내용을 쿼리하는 것입니다. 상태 필드가 아니라 프로젝트가 완료되었는지 여부를 나타내는 부울 플래그만 원한다고 가정해봅시다. 이를 다음과 같이 수행할 수 있습니다:
*[_type == "project"]{
_id, title,
"completed": count(milestones[status == 'completed']) > 0
}
여기서 우리는 milestones
를 가져오지만 상태가 "completed"
인 것만 선택합니다. 그런 다음 이 필터와 일치하는 마일스톤 수를 count()
합니다. 그 수가 0
보다 크면 결과는 true
입니다. 따라서 이제 결과는 다음과 같을 수 있습니다:
[
{
_id: "timmerhuis",
title: "Timmerhuis",
completed: true
},
…
]
위의 프로젝트 상태 예제에서 우리는 두 번째로 파이프 연산자 |
를 사용했습니다. 이를 좀 더 자세히 살펴보겠습니다:
*[_type == "project"]{
_id, title,
"status": milestones | order(year desc)[0].status
}
파이프 연산자는 왼쪽 피연산자에서 나온 결과를 오른쪽에 있는 연산에 전달합니다. "그런데 모든 GROQ 문이 그렇지 않은가요?"라고 묻는 소리가 들립니다. 맞습니다.
파이프 함수 (예 : 프로젝트 상태 예제에서의 order()
)를 사용하는 경우와 같이 일부 상황에서는 명시적인 파이프 연산자가 필요합니다. milestones order(year desc)
는 구문 오류가 될 것이므로 파이프 함수는 파이프 연산자로 시작되어야 합니다. 이렇게 사용합니다: milestones | order(year desc). score()
는 파이프 함수의 또 다른 예입니다. 따라서 파이프 연산자 앞에 나와야 합니다.
프로젝션에는 파이프 연산자를 붙일 수 있지만 선택 사항입니다. Expression { Projection }
과 Expression | { Projection }
은 모두 유효합니다.
파이프 연산자는 다른 문맥에서 유효하지 않으며 오류가 발생합니다.
다음과 같이 깊은 구조를 가진 문서를 고려해 봅시다:
{
_id: "alien",
_type: "movie",
title: "Alien",
poster: {
asset: {_ref: "image-1234"}
},
images: [
{
caption: "Sigourney Weaver and the cat Jones on set",
asset: {_ref: "image-1235"}
},
{
caption: "Bolaji Badejo suiting up for the role of the Alien",
asset: {_ref: "image-1236"}
},
]
}
따라서 우리에게는 포스터 이미지와 다른 이미지의 배열이 있는 영화가 있습니다. 각 이미지에는 캡션, 그리고 URL을 포함한 특정 이미지에 대한 모든 메타데이터를 나타내기 위해 자산 레코드에 대한 참조가 있습니다. 간소화된 자산 레코드는 다음과 같을 수 있습니다:
{
_id: "image-1234",
_type: "sanity.imageAsset",
url: "http:///cdn.sanity.io/images/…"
}
이제 우리는 포스터 이미지 URL을 검색하고 각 영화에 연결할 수 있습니다:
*[_type == "movie"]{
title,
"posterImage": poster.asset->url
}
그러나 다른 이미지에 대해서도 동일한 작업을 하고 싶다면 어떻게 해야 할까요? images
필드는 배열이므로 images.asset->url
과 같이 그대로 사용할 수 없습니다. 어떻게든 배열의 각 멤버에 asset->url
부분을 적용해야 합니다. 이를 위해 빈 필터를 추가해야 합니다. 이렇게 하면 images[].asset->url
을 사용하여 이미지 URL
을 간단한 배열로 반환할 수 있습니다. 따라서 전체 쿼리는 다음과 같을 것입니다:
*[_type == "movie"]{
title,
"imageUrls": images[].asset->url
}
이렇게하면 다음과 같은 결과가 생성됩니다:
[
{
title: "Alien",
imageUrls: ["http://cdn.sanity.io/…", "http://cdn.sanity.io/…"]
},
…
]
이미지와 관련된 더 풍부한 데이터 세트를 원한다면 다음과 같이 일반적인 프로젝션을 사용할 수 있습니다 (프로젝션을 각 배열 멤버에 적용하려면 빈 필터를 추가하는 것에 주의해야 함):
*[_type == "movie"]{
title,
"images": images[]{
caption,
"url": asset->url,
}
}
이제 결과는 다음과 같이 될 것입니다:
[
{
title: "Alien",
images: [
{
caption: "Sigourney Weaver and the cat Jones on set",
url: "http://cdn.sanity.io/…"
},
{
caption: "Bolaji Badejo suiting up for the role of the Alien",
url: "http://cdn.sanity.io/…"
}
]
},
…
]
때로는 문서의 일부 속성을 계산하고 싶지만, 여전히 모든 속성 집합을 반환하고 싶을 수 있습니다. 이는 사용자 정의 필드를 추가하기 위해 프로젝션이 필요하지만, 프로젝션을 지정하면 포함하려는 모든 필드를 명시적으로 나열해야 한다는 문제가 있습니다. 영화에서 배우의 수를 세고자 다음과 같이 작업하려고 할 때 문제가 발생합니다:
*[_type == "movie"]{
"actorCount": count(actors)
}
이에는 문제가 있습니다. 사용자 정의 필드를 추가하려고 했지만, 프로젝션이 필요했기 때문에 이제 얻게 된 것은 다음과 같습니다:
[
{actorCount: 3},
{actorCount: 27},
{actorCount: 15}
]
우리가 원한 것은 사용자 정의 필드와 일반 필드를 함께 얻는 것입니다. 이는 생략 연산자를 사용하여 달성할 수 있습니다. 다음과 같이 생략 연산자를 추가하여 명시적으로 지정한 필드뿐만 아니라 모든 것을 가져오도록 지정합니다:
*[_type == "movie"]{
"actorCount": count(actors),
...
}
이렇게 하면 다음과 같은 결과가 나타납니다:
{
{
title: "Alien",
releaseYear: 1979,
actorCount: 23,
// 그리고 많은 다른 필드, 아마도
},
// 그리고 많은 영화
}
GROQ API v1
에서는 생략 연산자의 위치가 중요하지 않았습니다. 명시적인 속성이 생략 연산자 다음에 오더라도 생략 연산자로 반환된 속성을 덮어씌웠습니다.
age
가 23
인 경우, 어떤 속성이 나이와 같다고 가정해 봅시다.
// GROQ API v1
*[]{
...,
'age': 45 // 이는 생략에서 반환된 나이 속성을 덮어씌웁니다. 따라서 age는 45입니다.
}
*[]{
'age': 45,
... // 생략에서 반환된 나이 값은 명시적으로 설정된 값보다 우선순위가 낮으므로 age는 45입니다.
}
GROQ API v2021-03-25
부터는 생략 연산자의 위치가 중요해졌습니다. 생략에서 반환된 속성을 오버라이드하려면 명시적으로 설정된 속성이 생략 연산자 뒤에 오면 됩니다. 즉, GROQ API v2021-03-25
부터는 프로젝션에서 가장 마지막에 있는 속성이 이기게 됩니다. 실제로 그 속성이 생략에서 반환된 것이더라도 그렇습니다.
// GROQ API v2021-03-25 이후
*[]{
...,
'age': 45 // 이는 생략에서 반환된 나이 속성을 덮어씌웁니다. 따라서 age는 45입니다.
}
*[]{
'age': 45,
... // 생략에서 반환된 나이 값은 명시적으로 설정된 값보다 우선순위가 낮으므로 age는 23입니다.
}
이러한 차이점은 역참조할 때 관찰될 수 있습니다. v1
에서는 명시적인 역참조 연산자를 생략 연산자 앞이나 뒤에 놓을 수 있었으며, 두 경우 모두 해당 문서를 따르게 되었습니다. 그러나 v2021-03-25
부터는 생략 연산자 뒤에 명시적인 역참조를 배치하면 예상한 동작을 수행하며, 생략 연산자를 마지막에 배치하면 원래의 (역참조되지 않은) 속성이 이기게 되어 _ref
와 _type
만 반환하게 됩니다.
팁: 생략 연산자를 사용할 때는 프로젝션에서 가장 먼저 나열해야 합니다. 뒤에 명시적으로 나열된 속성은 생략에서 반환된 동일한 속성을 덮어씁니다. 이는 일반적으로 원하는 동작입니다.
*
로 시작하지 않는 쿼리처음에 대부분의 GROQ 쿼리가 *
로 시작한다고 말했지만, 그럴 필요는 없습니다. 유효한 GROQ 식은 모든 쿼리의 전체일 수 있습니다. 다음은 유효한 쿼리입니다:
count(*)
이는 데이터 세트에 있는 문서의 수를 반환합니다. 다음도 유효합니다:
count(*[name match "sigourney"]) > 0
이는 데이터 세트의 모든 문서 중 "sigourney"
라는 단어가 포함된 이름 필드가 있는지 여부를 반환합니다.
더 유용하게도 프로젝션이 외부 문장이 될 수도 있습니다. 다음과 같이 세 개의 완전히 별개의 쿼리를 하나의 쿼리로 결합하고 그 결과를 포함하는 개체를 반환합니다. 이는 페이지 로드 속도를 높이는 유용한 방법입니다. 이러한 방식으로 쿼리를 결합함으로써 캐시 가능한 단일 쿼리에서 웹 페이지의 모든 핵심 콘텐츠를로드할 수 있습니다.
{
"mainStory": *[_id == "story-1234"],
"campaign": *[_id == "campaign-1234"],
"topStories": *[_type == "story"] | order(publishAt desc) [0..10]
}
다른 쿼리 언어와 마찬가지로 GROQ 쿼리를 개발하고 반복할 때 성능에 대해 인식하는 것이 중요합니다.
그러면 이로써 GROQ의 일상적인 사용에 필요한 대부분을 이해하는 데 필요한 내용을 다루었습니다. Query Cheat Sheet, GROQ Arcade 및 현재 지원되는 모든 연산자 및 함수에 대한 예제가 포함된 참조 문서를 확인해야 합니다.