Spanner Graph 쿼리 개요

이 문서에서는 그래프 패턴 일치를 위한 구문을 비롯해 Spanner Graph에서 Graph Query Language를 사용하는 방법을 간략하게 설명하고 그래프에 대해 쿼리를 실행하는 방법을 보여줍니다. Spanner Graph를 사용하면 쿼리를 실행하여 패턴을 찾고, 관계를 탐색하고, 속성 그래프 데이터에서 유용한 정보를 얻을 수 있습니다.

이 문서의 예시에서는 Spanner Graph 설정 및 쿼리에서 만든 그래프 스키마를 사용합니다. 이 스키마는 다음 다이어그램에 나와 있습니다.

Spanner Graph 스키마의 예시
그림 1.: Spanner Graph 스키마의 예시.

Spanner Graph 쿼리 실행

Google Cloud 콘솔, Google Cloud CLI, 클라이언트 라이브러리, REST API 또는 RPC API를 사용하여 Spanner Graph 쿼리를 실행할 수 있습니다.

Google Cloud 콘솔

다음 단계에서는Google Cloud 콘솔에서 쿼리를 실행하는 방법을 보여줍니다. 이 단계에서는 example-db라는 데이터베이스가 포함된 test-instance라는 인스턴스가 있다고 가정합니다. 데이터베이스가 있는 인스턴스를 만드는 방법은 Spanner Graph 설정 및 쿼리를 참조하세요.

  1. Google Cloud 콘솔에서 Spanner 인스턴스 페이지로 이동합니다.

    Spanner 인스턴스로 이동

  2. test-instance라는 인스턴스를 클릭합니다.

  3. 데이터베이스에서 example-db라는 데이터베이스를 클릭합니다.

  4. Spanner Studio를 열고 새 탭을 클릭하거나 편집기 탭을 사용합니다.

  5. 쿼리 편집기에 쿼리를 입력합니다.

  6. 실행을 클릭합니다.

gcloud CLI

gcloud CLI 명령줄 도구를 사용하여 쿼리를 제출하려면 다음을 수행하세요.

  1. 아직 설치하지 않았다면 gcloud CLI를 설치합니다.

  2. gcloud CLI에서 다음 명령어를 실행합니다.

    gcloud spanner databases execute-sql

자세한 내용은 Spanner CLI 빠른 시작을 참조하세요.

REST API

REST API를 사용하여 쿼리를 제출하려면 다음 명령어 중 하나를 사용하세요.

자세한 내용은 REST API를 사용하여 데이터 쿼리REST를 사용하여 Spanner 시작하기를 참조하세요.

RPC API

RPC API를 사용하여 쿼리를 제출하려면 다음 명령어 중 하나를 사용하세요.

클라이언트 라이브러리

Spanner 클라이언트 라이브러리로 쿼리를 실행하는 방법을 자세히 알아보려면 다음을 참조하세요.

Spanner 클라이언트 라이브러리에 대한 자세한 내용은 Spanner 클라이언트 라이브러리 개요를 참조하세요.

Spanner Graph 쿼리 결과 시각화

Google Cloud 콘솔의 Spanner Studio에서 Spanner Graph 쿼리 결과의 시각적 표현을 확인할 수 있습니다. 쿼리 시각화를 사용하면 반환된 요소(노드 및 에지)가 연결되는 방식을 확인할 수 있습니다. 이렇게 하면 표에서 결과를 볼 때 파악하기 어려운 패턴, 종속 항목, 이상치를 파악할 수 있습니다. 쿼리의 시각화를 보려면 쿼리가 JSON 형식의 전체 노드를 반환해야 합니다. 그렇지 않으면 쿼리 결과가 테이블 형식으로만 표시됩니다. 자세한 내용은 Spanner Graph 쿼리 시각화 사용을 참조하세요.

Spanner Graph 쿼리 구조

Spanner Graph 쿼리는 속성 그래프 이름, 노드 및 에지 패턴, 수량자와 같은 여러 구성요소로 구성됩니다. 이러한 구성요소를 사용하여 그래프에서 특정 패턴을 찾는 쿼리를 만듭니다. 각 구성요소는 이 문서의 그래프 패턴 일치 섹션에 설명되어 있습니다.

그림 2의 쿼리는 Spanner Graph 쿼리의 기본 구조를 보여줍니다. 쿼리는 GRAPH 절을 사용해서 대상 그래프 FinGraph를 지정하는 것으로 시작합니다. MATCH 절은 검색할 패턴을 정의합니다. 이 경우 Owns 에지를 통해 Account 노드에 연결된 Person 노드입니다. RETURN 절은 일치하는 노드의 어떤 속성을 반환할지 지정합니다.

Spanner Graph 쿼리 구조 예시
그림 2.: Spanner Graph 쿼리 구조의 예시

그래프 패턴 일치

그래프 패턴 일치는 그래프 내에서 특정 패턴을 찾습니다. 가장 기본적인 패턴은 노드와 일치하는 노드 패턴, 에지와 일치하는 에지 패턴과 같은 요소 패턴입니다.

노드 패턴

노드 패턴은 그래프의 노드와 일치합니다. 이 패턴에는 일치하는 괄호가 포함되어 있으며 선택적으로 그래프 패턴 변수, 라벨 표현식 및 속성 필터를 포함할 수 있습니다.

모든 노드 찾기

다음 쿼리는 그래프의 모든 노드를 반환합니다. 그래프 패턴 변수라고 부르는 n 변수는 일치 노드에 바인딩됩니다. 여기에서 노드 패턴은 그래프의 모든 노드와 일치합니다.

GRAPH FinGraph
MATCH (n)
RETURN LABELS(n) AS label, n.id;

이 쿼리는 labelid를 반환합니다.

라벨 id
계정 7
계정 16
계정 20
사람 1
사람 2
사람 3

특정 라벨이 있는 모든 노드 찾기

다음 쿼리는 그래프에서 Person 라벨이 있는 모든 노드를 찾습니다. 이 쿼리는 일치하는 노드의 labelid, name 속성을 반환합니다.

GRAPH FinGraph
MATCH (p:Person)
RETURN LABELS(p) AS label, p.id, p.name;

이 쿼리는 일치하는 노드의 다음 속성을 반환합니다.

라벨 id name
사람 1 Alex
사람 2 Dana
사람 3 Lee

라벨 표현식과 일치하는 모든 노드 찾기

하나 이상의 논리 연산자로 라벨 표현식을 만들 수 있습니다. 예를 들어 다음 쿼리는 그래프에서 Person 또는 Account 라벨이 있는 모든 노드를 일치시킵니다. 그래프 패턴 변수 nPerson 또는 Account 라벨이 있는 노드의 모든 속성을 노출합니다.

GRAPH FinGraph
MATCH (n:Person|Account)
RETURN LABELS(n) AS label, n.id, n.birthday, n.create_time;

이 쿼리의 다음 결과에서는

  • 모든 노드에 id 속성이 있습니다.
  • Account 라벨과 일치하는 노드에는 create_time 속성이 포함되지만 birthday 속성이 없습니다. 이러한 노드의 birthday 속성은 NULL입니다.
  • Person 라벨과 일치하는 노드에는 birthday 속성이 포함되지만 create_time 속성이 없습니다. 이러한 노드의 create_time 속성은 NULL입니다.
라벨 id 생일 create_time
계정 7 NULL 2020-01-10T14:22:20.222Z
계정 16 NULL 2020-01-28T01:55:09.206Z
계정 20 NULL 2020-02-18T13:44:20.655Z
사람 1 1991-12-21T08:00:00Z NULL
사람 2 1980-10-31T08:00:00Z NULL
사람 3 1986-12-07T08:00:00Z NULL

라벨 표현식과 속성 필터와 일치하는 모든 노드 찾기

이 쿼리는 그래프에서 Person 라벨이 있고 id 속성이 1과 동일한 모든 노드를 찾습니다.

GRAPH FinGraph
MATCH (p:Person {id: 1})
RETURN LABELS(p) AS label, p.id, p.name, p.birthday;

쿼리 결과는 다음과 같습니다.

라벨 id name 생일
사람 1 Alex 1991-12-21T08:00:00Z

WHERE 절을 사용해서 라벨 및 속성에 대해 보다 복잡한 필터링 조건을 형성할 수 있습니다.

다음 쿼리는 WHERE 절을 사용하여 속성에 대해 더 복잡한 필터링 조건을 형성합니다. 그래프에서 Person 라벨이 있고 birthday 속성이 1990-01-10 이전인 모든 노드와 일치합니다.

GRAPH FinGraph
MATCH (p:Person WHERE p.birthday < '1990-01-10')
RETURN LABELS(p) AS label, p.name, p.birthday;

쿼리 결과는 다음과 같습니다.

라벨 name 생일
사람 Dana 1980-10-31T08:00:00Z
사람 Lee 1986-12-07T08:00:00Z

에지 패턴

에지 패턴은 에지 또는 노드 간의 관계를 찾습니다. 에지 패턴은 대괄호([])로 묶여 있으며 방향을 나타내는 -, ->, <- 등의 기호가 포함됩니다. 에지 패턴에는 일치하는 에지에 바인딩할 그래프 패턴 변수가 선택적으로 포함될 수 있습니다.

일치하는 라벨이 있는 모든 에지 찾기

이 쿼리는 그래프에서 Transfers 라벨이 있는 모든 에지를 반환합니다. 쿼리는 그래프 패턴 변수 e를 일치하는 에지에 바인딩합니다.

GRAPH FinGraph
MATCH -[e:Transfers]->
RETURN e.Id as src_account, e.order_number

쿼리 결과는 다음과 같습니다.

src_account order_number
7 304330008004315
7 304120005529714
16 103650009791820
20 304120005529714
20 302290001255747

라벨 표현식과 속성 필터와 일치하는 모든 에지 찾기

이 쿼리의 에지 패턴은 라벨 표현식과 속성 필터를 사용하여 지정된 order_number와 일치하는 Transfers 라벨이 지정된 모든 에지를 찾습니다.

GRAPH FinGraph
MATCH -[e:Transfers {order_number: "304120005529714"}]->
RETURN e.Id AS src_account, e.order_number

쿼리 결과는 다음과 같습니다.

src_account order_number
7 304120005529714
20 304120005529714

모든 방향 에지 패턴을 사용하여 모든 에지 찾기

쿼리에서 any direction 에지 패턴(-[]-)을 사용하여 어느 방향으로든 에지를 일치시킬 수 있습니다. 다음 쿼리는 차단된 계정이 있는 모든 송금을 찾습니다.

GRAPH FinGraph
MATCH (account:Account)-[transfer:Transfers]-(:Account {is_blocked:true})
RETURN transfer.order_number, transfer.amount;

쿼리 결과는 다음과 같습니다.

order_number 금액
304330008004315 300
304120005529714 100
103650009791820 300
302290001255747 200

경로 패턴

경로 패턴은 대체 노드 및 에지 패턴으로부터 빌드됩니다.

경로 패턴을 사용하여 특정 노드에서 모든 경로 찾기

다음 쿼리는 id2와 동일한 Person이 소유하는 계정에서 시작된 모든 송금을 찾습니다.

일치하는 각 결과는 Owns 에지를 사용하는 연결된 Account를 통한 Person {id: 2}부터 Transfers 에지를 사용하는 다른 Account까지의 경로를 나타냅니다.

GRAPH FinGraph
MATCH
  (p:Person {id: 2})-[:Owns]->(account:Account)-[t:Transfers]->
  (to_account:Account)
RETURN
  p.id AS sender_id, account.id AS from_id, to_account.id AS to_id;

쿼리 결과는 다음과 같습니다.

sender_id from_id to_id
2 20 7
2 20 16

정량화된 경로 패턴

정량화된 패턴은 지정된 범위 내에서 패턴을 반복합니다.

정량화된 에지 패턴 찾기

가변 길이의 경로를 찾으려면 에지 패턴에 수량자를 적용하면 됩니다. 다음 쿼리는 id7인 소스 Account에서 1~3번 송금이 수행된 대상 계정을 찾아 이를 보여줍니다.

이 쿼리는 수량자 {1, 3}을 에지 패턴 -[e:Transfers]->에 적용합니다. 이는 Transfers 에지 패턴이 한 번, 두 번 또는 세 번 반복되는 경로와 일치하도록 쿼리에 지시합니다. WHERE 절은 소스 계정을 결과에서 제외하는 데 사용됩니다. ARRAY_LENGTH 함수는 group variable e에 액세스하는 데 사용됩니다. 자세한 내용은 액세스 그룹 변수를 참조하세요.

GRAPH FinGraph
MATCH (src:Account {id: 7})-[e:Transfers]->{1, 3}(dst:Account)
WHERE src != dst
RETURN src.id AS src_account_id, ARRAY_LENGTH(e) AS path_length, dst.id AS dst_account_id;

쿼리 결과는 다음과 같습니다.

src_account_id path_length dst_account_id
7 1 16
7 1 16
7 1 16
7 3 16
7 3 16
7 2 20
7 2 20

결과의 일부 행이 반복됩니다. 이는 동일한 소스 노드와 대상 노드 사이에 패턴이 일치하는 여러 경로가 존재할 수 있으며, 쿼리에서 이러한 경로를 모두 반환하기 때문입니다.

정량화된 경로 패턴 일치

다음 쿼리는 차단된 중간 계정을 통해 1~2개의 Transfers 에지가 있는 Account 노드 사이의 경로를 찾습니다.

괄호로 묶인 경로 패턴이 정량화되고 WHERE 절에서 반복 패턴 조건을 지정합니다.

GRAPH FinGraph
MATCH
  (src:Account)
  ((a:Account)-[:Transfers]->(b:Account {is_blocked:true}) WHERE a != b){1,2}
    -[:Transfers]->(dst:Account)
RETURN src.id AS src_account_id, dst.id AS dst_account_id;

쿼리 결과는 다음과 같습니다.

src_account_id dst_account_id
7 20
7 20
20 20

그룹 변수

정량화된 패턴에 선언된 그래프 패턴 변수는 해당 패턴 외부에서 액세스되었을 때 그룹 변수가 됩니다. 그런 다음 일치하는 그래프 요소의 배열에 바인딩됩니다.

그룹 변수를 배열로 액세스할 수 있습니다. 그래프 요소는 일치하는 경로를 따라 나타난 순서대로 보존됩니다. 가로 집계를 사용해서 그룹 변수를 집계할 수 있습니다.

그룹 변수 액세스

다음 예시에서 e 변수는 다음과 같이 액세스됩니다.

  • 정량화된 패턴 내에 있을 때 WHERE 절에서 e.amount > 100 조건을 가진 단일 에지에 바인딩된 그래프 패턴 변수
  • 정량화된 패턴 외부에 있을 때 RETURN 문에서 ARRAY_LENGTH(e)의 에지 요소 배열에 바인딩된 그룹 변수
  • 정량화된 패턴 외에서 SUM(e.amount)으로 집계된 에지 요소 배열에 바인딩된 그룹 변수 다음은 가로 집계 예시입니다.
GRAPH FinGraph
MATCH
  (src:Account {id: 7})-[e:Transfers WHERE e.amount > 100]->{0,2}
  (dst:Account)
WHERE src.id != dst.id
LET total_amount = SUM(e.amount)
RETURN
  src.id AS src_account_id, ARRAY_LENGTH(e) AS path_length,
  total_amount, dst.id AS dst_account_id;

쿼리 결과는 다음과 같습니다.

src_account_id path_length total_amount dst_account_id
7 1 300 16
7 2 600 20

경로 검색 프리픽스

소스 및 대상 노드를 공유하는 그룹 내에서 일치하는 경로를 제한하려면 ANY 또는 ANY SHORTEST 경로 검색 프리픽스를 사용하면 됩니다. 이러한 프리픽스는 전체 경로 패턴 앞에만 적용할 수 있고 괄호 안에 적용할 수 없습니다.

ANY를 사용하여 일치

다음 쿼리는 지정된 Account 노드에서 한 번 또는 두 번의 Transfers로 도달할 수 있는 모든 고유 계정을 찾습니다.

ANY 경로 검색 프리픽스는 쿼리가 srcdst Account 노드의 고유 쌍 사이에 경로를 하나만 반환하도록 보장합니다. 다음 예시에서는 소스 Account 노드에서 {id: 16}을 사용하여 Account 노드에 도달하는 2개의 다른 경로가 있지만 쿼리에서는 하나의 경로만 반환합니다.

GRAPH FinGraph
MATCH ANY (src:Account {id: 7})-[e:Transfers]->{1,2}(dst:Account)
LET ids_in_path = ARRAY_CONCAT(ARRAY_AGG(e.Id), [dst.Id])
RETURN src.id AS src_account_id, dst.id AS dst_account_id, ids_in_path;

쿼리 결과는 다음과 같습니다.

src_account_id dst_account_id ids_in_path
7 16 7,16
7 20 7,16,20

그래프 패턴

그래프 패턴은 쉼표(,)로 구분된 하나 이상의 경로 패턴으로 구성됩니다. 그래프 패턴에는 WHERE 절을 포함할 수 있습니다. 이를 통해 경로 패턴에 있는 모든 그래프 패턴 변수에 액세스하여 필터링 조건을 형성할 수 있습니다. 각 경로 패턴은 경로 컬렉션을 생성합니다.

그래프 패턴을 사용하여 찾기

다음 쿼리는 소스 계정에서 차단된 계정으로 자금이 송금되는 과정에서, 거래 금액이 200을 초과하는 트랜잭션에 관련된 중개 계정과 해당 소유자를 식별합니다.

다음 경로 패턴은 그래프 패턴을 형성합니다.

  • 첫 번째 패턴은 중개 계정을 사용해서 하나의 계정에서 차단된 계정으로 송금이 수행된 경로를 찾습니다.
  • 두 번째 패턴은 한 계정에서 계정 소유 인물로의 경로를 찾습니다.

interm 변수는 두 경로 패턴 간의 공통 링크로 작동합니다. interm은 두 경로 패턴에 있는 동일한 요소 노드를 참조해야 합니다. 이렇게 하면 interm 변수를 기반으로 등가 조인 작업이 생성됩니다.

GRAPH FinGraph
MATCH
  (src:Account)-[t1:Transfers]->(interm:Account)-[t2:Transfers]->(dst:Account),
  (interm)<-[:Owns]-(p:Person)
WHERE dst.is_blocked = TRUE AND t1.amount > 200 AND t2.amount > 200
RETURN
  src.id AS src_account_id, dst.id AS dst_account_id,
  interm.id AS interm_account_id, p.id AS owner_id;

쿼리 결과는 다음과 같습니다.

src_account_id dst_account_id interm_account_id owner_id
20 16 7 1

선형 쿼리 문

여러 그래프 문을 하나로 연결해서 선형 쿼리 문을 만들 수 있습니다. 문이 실행되는 순서는 쿼리에 표시된 순서와 동일합니다.

  • 각 문은 이전 문의 출력을 입력으로 사용합니다. 첫 번째 문은 입력이 비어 있습니다.

  • 마지막 문의 출력이 최종 결과입니다.

예를 들어 선형 쿼리 문을 사용하여 차단된 계정에 대한 최대 송금을 찾을 수 있습니다. 다음 쿼리는 차단된 계정으로 나가는 송금액이 가장 큰 계정과 그 소유자를 찾습니다.

GRAPH FinGraph
MATCH (src_account:Account)-[transfer:Transfers]->(dst_account:Account {is_blocked:true})
ORDER BY transfer.amount DESC
LIMIT 1
MATCH (src_account:Account)<-[owns:Owns]-(owner:Person)
RETURN src_account.id AS account_id, owner.name AS owner_name;

다음 표는 각 문 간에 전달되는 중간 결과를 보여줌으로써 이 프로세스를 설명합니다. 간단한 설명을 위해 일부 속성만 표시됩니다.

명세서 중간 결과(축약됨)
MATCH
  (src_account:Account)
    -[transfer:Transfers]->
  (dst_account:Account {is_blocked:true})
src_account transfer dst_account
{id: 7} {amount: 300.0} {id: 16, is_blocked: true}
{id: 7} {amount: 100.0} {id: 16, is_blocked: true}
{id: 20} {amount: 200.0} {id: 16, is_blocked: true}

ORDER BY transfer.amount DESC
src_account transfer dst_account
{id: 7} {amount: 300.0} {id: 16, is_blocked: true}
{id: 20} {amount: 200.0} {id: 16, is_blocked: true}
{id: 7} {amount: 100.0} {id: 16, is_blocked: true}

LIMIT 1
src_account transfer dst_account
{id: 7} {amount: 300.0} {id: 16, is_blocked: true}

MATCH
  (src_account:Account)
    <-[owns:Owns]-
  (owner:Person)
src_account transfer dst_account owns owner
{id: 7} {amount: 300.0} {id: 16, is_blocked: true} {person_id: 1, account_id: 7} {id: 1, name: Alex}
RETURN
  src_account.id AS account_id,
  owner.name AS owner_name
        
account_id owner_name
7 Alex

쿼리 결과는 다음과 같습니다.

account_id owner_name
7 Alex

return 문

RETURN은 일치하는 패턴에서 반환할 항목을 지정합니다. 이 문은 그래프 패턴 변수에 액세스하고 표현식과 ORDER BY, GROUP BY와 같은 절을 포함할 수 있습니다.

Spanner Graph는 그래프 요소를 쿼리 결과로 반환하는 것을 지원하지 않습니다. 전체 그래프 요소를 반환하려면 TO_JSON 함수 또는 SAFE_TO_JSON 함수를 사용하세요. 이 두 함수 중 SAFE_TO_JSON을 사용하는 것이 좋습니다.

그래프 요소를 JSON으로 반환

GRAPH FinGraph
MATCH (n:Account {id: 7})
-- Returning a graph element in the final results is NOT allowed. Instead, use
-- the TO_JSON function or explicitly return the graph element's properties.
RETURN TO_JSON(n) AS n;
GRAPH FinGraph
MATCH (n:Account {id: 7})
-- Certain fields in the graph elements, such as TOKENLIST, can't be returned
-- in the TO_JSON function. In those cases, use the SAFE_TO_JSON function instead.
RETURN SAFE_TO_JSON(n) AS n;

쿼리 결과는 다음과 같습니다.

n
{"identifier":"mUZpbkdyYXBoLkFjY291bnQAeJEO","kind":"node","labels":["Account"],"properties":{"create_time":"2020-01-10T14:22:20.222Z","id":7,"is_blocked":false,"nick_name":"Vacation Fund"}}

NEXT 키워드로 더 큰 쿼리 작성

NEXT 키워드를 사용해서 여러 그래프 선형 쿼리 문을 하나로 연결할 수 있습니다. 첫 번째 문은 빈 입력을 받고 각 후속 문의 출력은 다음 문의 입력이 됩니다.

다음 예시에서는 여러 그래프 선형 문을 연결해서 들어오는 송금액이 가장 큰 계정의 소유자를 찾습니다. 동일한 변수(예: account)를 사용하여 여러 선형 문 간의 동일한 그래프 요소를 참조할 수 있습니다.

GRAPH FinGraph
MATCH (:Account)-[:Transfers]->(account:Account)
RETURN account, COUNT(*) AS num_incoming_transfers
GROUP BY account
ORDER BY num_incoming_transfers DESC
LIMIT 1

NEXT

MATCH (account:Account)<-[:Owns]-(owner:Person)
RETURN account.id AS account_id, owner.name AS owner_name, num_incoming_transfers;

쿼리 결과는 다음과 같습니다.

account_id owner_name num_incoming_transfers
16 Lee 3

함수 및 표현식

Spanner Graph 쿼리에서 모든 GoogleSQL 함수(집계 함수 및 스칼라 함수 모두), 연산자, 조건부 표현식을 사용할 수 있습니다. Spanner Graph는 그래프 관련 함수와 연산자도 지원합니다.

기본 제공 함수 및 연산자

다음 함수연산자는 GQL에서 사용됩니다.

  • PROPERTY_EXISTS(n, birthday): nbirthday 속성을 가지는지 여부를 반환합니다.
  • LABELS(n): n의 라벨을 그래프 스키마에 정의된 대로 반환합니다.
  • PROPERTY_NAMES(n): n의 속성 이름을 반환합니다.
  • TO_JSON(n): n을 JSON 형식으로 반환합니다. 자세한 내용은 TO_JSON 함수를 참조하세요.

PROPERTY_EXISTS 조건자, LABELS 함수, TO_JSON 함수는 물론 ARRAY_AGGCONCAT과 같은 다른 기본 제공 함수도 사용할 수 있습니다.

GRAPH FinGraph
MATCH (person:Person)-[:Owns]->(account:Account)
RETURN person, ARRAY_AGG(account.nick_name) AS accounts
GROUP BY person

NEXT

RETURN
  LABELS(person) AS labels,
  TO_JSON(person) AS person,
  accounts,
  CONCAT(person.city, ", ", person.country) AS location,
  PROPERTY_EXISTS(person, is_blocked) AS is_blocked_property_exists,
  PROPERTY_EXISTS(person, name) AS name_property_exists
LIMIT 1;

쿼리 결과는 다음과 같습니다.

is_blocked_property_exists name_property_exists 라벨 계정 위치 사람
false true Person ["Vacation Fund"] Adelaide, Australia {"identifier":"mUZpbkdyYXBoLlBlcnNvbgB4kQI=","kind":"node","labels":["Person"],"properties":{"birthday":"1991-12-21T08:00:00Z","city":"Adelaide","country":"Australia","id":1,"name":"Alex"}}

서브 쿼리

서브 쿼리는 다른 쿼리에 중첩된 쿼리입니다. 다음은 Spanner Graph 서브 쿼리 규칙을 보여줍니다.

  • 서브 쿼리는 중괄호 {} 쌍으로 묶어서 표시합니다.
  • 서브 쿼리는 현재 그래프를 지정하기 위해 선행 GRAPH 절로 시작할 수 있습니다. 지정된 그래프는 외부 쿼리에 사용된 것과 동일할 필요가 없습니다.
  • 서브 쿼리에서 GRAPH 절을 생략하면 다음 결과가 발생합니다.
    • 현재 그래프가 가장 가까운 외부 쿼리 컨텍스트에서 유추됩니다.
    • 서브 쿼리는 MATCH를 사용한 그래프 패턴 일치 문으로부터 시작해야 합니다.
  • 서브 쿼리 범위 외부에 선언된 그래프 패턴 변수는 서브 쿼리 내에 다시 선언할 수 없지만 서브 쿼리 내부의 표현식 또는 함수에서 참조할 수 있습니다.

서브 쿼리를 사용하여 각 계정의 총 송금액 찾기

다음 쿼리는 VALUE 서브 쿼리 사용을 보여줍니다. 서브 쿼리는 VALUE 키워드를 프리픽스로 표시하고 중괄호 {}로 묶어서 표시됩니다. 쿼리는 한 계정에서 시작된 총 송금 횟수를 반환합니다.

GRAPH FinGraph
MATCH (p:Person)-[:Owns]->(account:Account)
RETURN p.name, account.id AS account_id, VALUE {
  MATCH (a:Account)-[transfer:Transfers]->(:Account)
  WHERE a = account
  RETURN COUNT(transfer) AS num_transfers
} AS num_transfers;

쿼리 결과는 다음과 같습니다.

name account_id num_transfers
Alex 7 2
Dana 20 2
Lee 16 1

지원되는 서브 쿼리 표현식 목록은 Spanner Graph 서브 쿼리를 참조하세요.

서브 쿼리를 사용하여 각 사용자가 소유한 계정 찾기

다음 쿼리는 인라인 서브 쿼리와 함께 CALL 문을 사용합니다. MATCH (p:Person) 문은 p라는 단일 열이 있는 테이블을 만듭니다. 이 표의 각 행에는 Person 노드가 포함됩니다. CALL (p) 문은 이 작업 테이블의 각 행에 대해 묶인 서브 쿼리를 실행합니다. 서브 쿼리는 일치하는 각 사람 p가 소유한 계정을 찾습니다. 동일한 사람의 여러 계정은 계정 ID로 정렬됩니다.

이 예시에서는 MATCH (p:Person) 절에서 외부 범위 노드 변수 p를 선언합니다. CALL (p) 문은 이 변수를 참조합니다. 이 선언을 사용하면 서브 쿼리의 경로 패턴에서 노드 변수를 다시 선언하거나 다중 선언할 수 있습니다. 이렇게 하면 내부 및 외부 p 노드 변수가 그래프의 동일한 Person 노드에 바인딩됩니다. CALL 문이 노드 변수 p를 선언하지 않으면 서브 쿼리는 다시 선언된 변수 p를 새 변수로 취급합니다. 이 새 변수는 외부 범위 변수와 독립적이며 서브 쿼리는 다른 결과를 반환하므로 이를 다중 선언하지 않습니다. 자세한 내용은 CALL을 참조하세요.

GRAPH FinGraph
MATCH (p:Person)
CALL (p) {
  MATCH (p)-[:Owns]->(a:Account)
  RETURN a.Id AS account_Id
  ORDER BY account_Id
}
RETURN p.name AS person_name, account_Id
ORDER BY person_name, account_Id;

결과

person_name account_Id
Alex 7
Dana 20
Lee 16

쿼리 매개변수

매개변수를 사용해서 Spanner Graph를 쿼리할 수 있습니다. 자세한 내용은 구문을 참조하고 Spanner 클라이언트 라이브러리에서 파라미터를 사용한 데이터 쿼리 방법을 알아보세요.

다음 쿼리는 쿼리 매개변수 사용을 보여줍니다.

GRAPH FinGraph
MATCH (person:Person {id: @id})
RETURN person.name;

그래프 및 테이블 함께 쿼리

Graph 쿼리를 SQL과 함께 사용해서 단일 문으로 Graphs 및 Tables의 정보를 함께 액세스할 수 있습니다.

GRAPH_TABLE 연산자는 선형 그래프 쿼리를 사용해서 SQL 쿼리로 통합할 수 있는 테이블 형식으로 결과를 반환합니다. 이러한 상호 운용성 덕분에 비그래프 콘텐츠로 그래프 쿼리 결과를 향상시킬 수 있으며, 그 반대의 경우도 마찬가지입니다.

예를 들어 다음 예시에 표시된 것처럼 CreditReports 테이블을 만들고 몇 가지 신용 보고서를 삽입할 수 있습니다.

CREATE TABLE CreditReports (
  person_id     INT64 NOT NULL,
  create_time   TIMESTAMP NOT NULL,
  score         INT64 NOT NULL,
) PRIMARY KEY (person_id, create_time);
INSERT INTO CreditReports (person_id, create_time, score)
VALUES
  (1,"2020-01-10 06:22:20.222", 700),
  (2,"2020-02-10 06:22:20.222", 800),
  (3,"2020-03-10 06:22:20.222", 750);

그런 다음 GRAPH_TABLE에서 그래프 패턴 일치를 통해 특정 인물을 식별하고 그래프 쿼리 결과를 CreditReports 테이블과 조인하여 신용 점수를 가져올 수 있습니다.

SELECT
  gt.person.id,
  credit.score AS latest_credit_score
FROM GRAPH_TABLE(
  FinGraph
  MATCH (person:Person)-[:Owns]->(:Account)-[:Transfers]->(account:Account {is_blocked:true})
  RETURN DISTINCT person
) AS gt
JOIN CreditReports AS credit
  ON gt.person.id = credit.person_id
ORDER BY credit.create_time;

쿼리 결과는 다음과 같습니다.

person_id latest_credit_score
1 700
2 800

다음 단계

쿼리 조정을 위한 권장사항 알아보기