-[edge_body]-> left to right <-[edge_body]- right to left -[edge_body]- either direction
굵게 키워드 · 기울임 직접 채우는 자리 · [ ] 생략 가능 · ... 반복 가능. 구문 표기 규약을 참고하십시오.
{#match-description}
## 설명
`MATCH`는 그래프를 읽습니다. 자기 패턴을 저장된 정점과 간선 위에 얹을 수 있는 모든 방식마다 행
하나를 내놓습니다. 패턴의 이름 있는 요소는 각각 그것이 일치시킨 정점·간선·경로에 바인딩됩니다.
파이프라인의 뒤따르는 절이 그 바인딩을 봅니다. 파이프라인 가운데의 `MATCH`는 들어오는 행마다 한 번
실행되어 자기 일치를 그 행에 조인하며, 관계형 쿼리에서 조인이 행을 더하는 것과 같습니다.
- **변수가 없는** 패턴 요소도 일치됩니다. 뒤에서 그것을 가리킬 수 없을 뿐입니다. 그 요소가 모양을
제약하는 데만 필요하다면 변수를 빼십시오.
- **레이블**은 요소를 그 레이블과 자식 레이블로 제한하고, `ONLY`는 그 레이블 자체로 제한합니다.
레이블이 없으면 요소는 그래프의 모든 정점 또는 모든 간선에 일치합니다.
- 패턴 안의 **속성 맵**은 그것이 적은 키마다 같음을 검사하는 것입니다. 축약형입니다.
`(m:movie {year: 1999})`와 `(m:movie) WHERE m.year = 1999`는 같은 정점에 일치합니다.
- **쉼표**는 하나의 `MATCH` 안에서 독립적인 패턴을 구분합니다. 변수를 공유하는 패턴은 그 변수로
조인되고, 아무것도 공유하지 않는 패턴은 곱집합을 만듭니다.
- 하나의 패턴 일치 안에서 **같은 간선을 두 번 쓰지 않습니다.** 정점 바인딩은 반복될 수 있어서
패턴이 삼각형을 닫을 수는 있지만, 두 홉 패턴이 자기가 지나온 간선으로 되돌아가는 일은 없습니다.
- **간선 변수**는 패턴마다 한 번만 쓸 수 있습니다. 다시 쓰면 `duplicate variable`이 나옵니다.
**정점 변수**는 반복할 수 있고, 그러면 두 자리가 같은 정점으로 제약됩니다.
- `MATCH`는 쿼리를 시작하거나 첫 절 뒤 어디에든 놓일 수 있습니다. 쿼리를 끝내지는 않습니다. 쿼리는
`RETURN`, `FINISH`, 또는 쓰기 절로 끝나야 합니다.
`OPTIONAL MATCH`는 패턴이 아무것도 찾지 못한 입력 행을 남기고, 그 행을 버리는 대신 패턴의 변수를
null로 바인딩합니다. 그것은 자기 페이지가 있습니다. [`OPTIONAL MATCH`](optional-match.md)입니다.
{#match-parameters}
## 매개변수
pattern
: 경로 패턴 하나이며, 앞에 `path_variable =`을 붙일 수도 있습니다. 쉼표로 구분해 여러 개 나열할 수
있습니다.
path_variable
: 일치한 경로 전체에 바인딩되는 이름이며, 그 정점과 간선을 순서대로 담은 값입니다. 경로 함수
`length()`·`nodes()`·`edges()`로 읽습니다. 그 이름은 식별자여야 합니다. `path`처럼 예약되지 않은
키워드도 따옴표로 감싸지 않으면(`` "path" ``) 이 자리에서는 거부됩니다.
variable
: 일치한 정점이나 간선에 바인딩되는 이름입니다. 생략할 수 있습니다. 이 절 뒤의 모든 절에서
보입니다.
label
: 정점 패턴에서는 정점 레이블, 간선 패턴에서는 간선 레이블입니다. 요소마다 레이블 하나입니다.
ONLY
: 자식 레이블을 제외하므로, 그 요소는 해당 레이블 자기 테이블의 행에만 일치하고 그것을 상속한
것에는 일치하지 않습니다. 레이블이 있어야 합니다.
property_map
: 맵 리터럴, 또는 그것을 담은 쿼리 매개변수입니다. 각 키는 그 요소의 같은 이름 속성과 같은지
비교됩니다.
min, max
: 가변 길이 간선 패턴이 지나는 간선 수의 경계입니다. `*n`은 정확히 *n* 홉, `*m..n`은 *m*과 *n*
사이, `*m..`은 *m* 이상, `*..n`은 *n* 이하, `*`만 쓰면 하나 이상입니다.
condition
: 일치 결과를 걸러 내는 불리언 표현식이며, 패턴의 모든 변수가 바인딩된 상태에서 평가됩니다.
[`WHERE`](where.md)를 참고하십시오.
{#match-examples}
## 예제
모든 예제는 [예제 데이터셋](../../get_started/example-dataset.md)에서 실행됩니다.
{#match-find-one-vertex-by-a-property}
### 속성으로 정점 하나 찾기
```cypher
MATCH (p:person {name: 'Keanu Reeves'})
RETURN p;
```
```
p
---------------------------------------------------
person[4.1]{"born": 1964, "name": "Keanu Reeves"}
(1 row)
```
정점은 `label[id]{properties}` 형태로 출력됩니다. `4.1`이 그 그래프 id이고, `id(p)`로 읽습니다.
`p.id`는 `id`라는 이름의 속성을 읽는 것이고, 그런 속성은 없습니다.
{#match-follow-an-edge-in-one-direction}
### 한 방향으로 간선 따라가기
```cypher
MATCH (p:person)-[r:acted_in]->(m:movie {title: 'The Matrix'})
RETURN p.name AS actor, r.role AS role
ORDER BY actor;
```
```
actor | role
----------------------+------------
"Carrie-Anne Moss" | "Trinity"
"Keanu Reeves" | "Neo"
"Laurence Fishburne" | "Morpheus"
(3 rows)
```
양 끝점과 간선 모두에 레이블이 있고, 간선은 `r`에 바인딩되어 그 `role` 속성을 투영할 수 있습니다.
Cypher의 `RETURN`이 jsonb를 내놓으므로 문자열 값은 따옴표와 함께 돌아옵니다.
{#match-leave-out-the-elements-you-do-not-need}
### 필요하지 않은 요소 빼기
```cypher
MATCH (p:person {name: 'Christopher Nolan'})-[:directed]->(m)
RETURN m.title AS film
ORDER BY film;
```
```
film
----------------
"Inception"
"Interstellar"
(2 rows)
```
간선에는 변수가 없고 먼 쪽 끝점에는 레이블이 없습니다. 둘 다 여전히 일치를 제약하며, 어느 쪽도
바인딩 비용을 들이지 않습니다.
{#match-match-an-edge-in-either-direction}
### 어느 방향이든 간선 일치시키기
화살촉이 없는 간선 패턴은 간선이 어느 쪽을 가리키든 일치시킵니다:
```cypher
MATCH (m:movie {title: 'Total Recall'})-[:related_to]-(n:movie)
RETURN n.title AS neighbour
ORDER BY neighbour;
```
```
neighbour
--------------
"Inception"
"The Matrix"
(2 rows)
```
`Total Recall`에는 나가는 `related_to` 간선 하나와 들어오는 것 하나가 있습니다. 양쪽 끝에 화살촉을
붙인 `<-[:related_to]->`도 같은 뜻입니다.
{#match-join-two-patterns-on-a-shared-variable}
### 공유 변수로 두 패턴 조인하기
```cypher
MATCH (a:person)-[:acted_in]->(m:movie), (d:person)-[:directed]->(m)
WHERE m.title = 'The Matrix'
RETURN a.name AS actor, d.name AS director
ORDER BY actor, director;
```
```
actor | director
----------------------+-------------------
"Carrie-Anne Moss" | "Lana Wachowski"
"Carrie-Anne Moss" | "Lilly Wachowski"
"Keanu Reeves" | "Lana Wachowski"
"Keanu Reeves" | "Lilly Wachowski"
"Laurence Fishburne" | "Lana Wachowski"
"Laurence Fishburne" | "Lilly Wachowski"
(6 rows)
```
두 패턴 모두 `m`을 언급하므로 그것으로 조인됩니다. 연달아 오는 `MATCH` 절 두 개도 같은 결과를 낼
것이고, 가운데에서 만나는 하나의 패턴
`(a:person)-[:acted_in]->(m:movie)<-[:directed]-(d:person)`도 그렇습니다.
{#match-name-the-whole-path}
### 경로 전체에 이름 붙이기
경로 자체를 바인딩하려면 패턴 앞에 `variable =`을 두십시오:
```cypher
MATCH p = (a:movie {title: 'The Matrix'})-[:related_to*1..3]->(b:movie)
RETURN length(p) AS hops, [x IN nodes(p) | x.title] AS route
ORDER BY hops, route;
```
```
hops | route
------+---------------------------------------------------------------------------------------------
1 | ["The Matrix", "The Matrix Reloaded"]
1 | ["The Matrix", "The Terminator"]
1 | ["The Matrix", "Total Recall"]
2 | ["The Matrix", "The Matrix Reloaded", "The Matrix Revolutions"]
2 | ["The Matrix", "The Terminator", "Terminator 2: Judgment Day"]
2 | ["The Matrix", "Total Recall", "Inception"]
3 | ["The Matrix", "The Matrix Reloaded", "The Matrix Revolutions", "The Matrix Resurrections"]
(7 rows)
```
{#match-walk-a-variable-number-of-edges}
### 정해지지 않은 수의 간선 걷기
간선 패턴에 붙인 `*`가 그것을 반복합니다. 각 경계는 생략할 수 있습니다:
```cypher
MATCH (m:movie {title: 'The Matrix'})-[:related_to*2]->(n:movie)
RETURN n.title AS reached
ORDER BY reached;
```
```
reached
------------------------------
"Inception"
"Terminator 2: Judgment Day"
"The Matrix Revolutions"
(3 rows)
```
하한이 `0`이면 길이 0인 경로가 포함되므로, 시작 정점도 답 중 하나가 됩니다:
```cypher
MATCH (m:movie {title: 'The Matrix'})-[:related_to*0..1]->(n:movie)
RETURN n.title AS reached
ORDER BY reached;
```
```
reached
-----------------------
"The Matrix"
"The Matrix Reloaded"
"The Terminator"
"Total Recall"
(4 rows)
```
{#match-exclude-child-labels-with-only}
### ONLY로 자식 레이블 제외하기
레이블은 자식 레이블에도 일치합니다. 레이블이 테이블이고 자식 레이블이 그것을 상속하기
때문입니다. `ONLY`는 일치 범위를 그 레이블 하나로 좁힙니다. 차이를 보려면 `person`에 자식 레이블을
하나 주십시오:
```cypher
CREATE VLABEL crew INHERITS (person);
CREATE (:crew {name: 'Bill Pope', born: 1952});
```
```
CREATE VLABEL
UPDATE 1
```
```cypher
MATCH (p:person) RETURN count(*) AS people;
```
```
people
--------
29
(1 row)
```
```cypher
MATCH (p:person ONLY) RETURN count(*) AS people;
```
```
people
--------
28
(1 row)
```
`ONLY`는 레이블 뒤, 속성 맵 앞에 놓입니다. `(p:person ONLY {name: 'Keanu Reeves'})`처럼입니다.
간선 패턴 `-[r:acted_in ONLY]->`에서도 같게 동작합니다. 준비한 것은 이렇게 되돌립니다:
```cypher
MATCH (p:crew) DETACH DELETE p;
DROP VLABEL crew;
```
```
UPDATE 1
DROP VLABEL
```
{#match-filter-the-matches-with-where}
### WHERE로 일치 결과 걸러 내기
`MATCH`에 붙인 `WHERE`는 뒤에 오는 단계가 아니라 그 일치의 일부입니다:
```cypher
MATCH (m:movie) WHERE m.year > 2015
RETURN m.title AS film, m.year AS year
ORDER BY year, film;
```
```
film | year
----------------------------+------
"Blade Runner 2049" | 2017
"The Matrix Resurrections" | 2021
(2 rows)
```
{#match-match-edges-of-several-labels}
### 여러 레이블의 간선 일치시키기
간선 패턴에는 레이블이 최대 하나입니다. 둘을 나열하면 오류가 납니다:
```cypher
MATCH (p:person)-[r:acted_in|directed]->(m:movie) RETURN count(r);
```
```
ERROR: multiple types for relationship not supported
```
대신 레이블 없는 간선을 일치시키고 그 레이블을 `WHERE`에서 검사하십시오:
```cypher
MATCH (p:person)-[r]->(m:movie)
WHERE label(r) IN ['acted_in', 'directed']
RETURN count(r) AS edges;
```
```
edges
-------
46
(1 row)
```
`label()`은 요소의 레이블을 문자열로 반환합니다. 그래서 이름 목록에 대한 `IN`이 일반적인
형태이고, 간선 레이블의 집합에 일치시키는 유일한 방법입니다.
{#match-notes}
## 참고
레이블 검사는 `WHERE` 안의 콜론이 아니라 `label(n) = '...'`에 씁니다. `WHERE n:movie`는 구문
오류이고, 패턴만 조건으로 쓴 것도 그렇습니다. `WHERE (m)-[:related_to]->(:movie)`는 파싱되지
않습니다. 패턴이 존재하는지 검사하려면
`WHERE EXISTS { MATCH (m)-[:related_to]->(:movie) }`를 쓰십시오.
속성 맵은 jsonb 값을 비교하고, 속성과의 비교도 그렇습니다. 리터럴의 타입이 저장된 타입과 맞지
않을 때 그것이 문제가 됩니다. [`WHERE`](where.md)를 참고하십시오.
```{note}
이름 붙인 경로 변수는 요소 변수보다 좁게 파싱됩니다. `(path)`는 받아들여지는 정점 변수이지만,
`path`가 키워드이므로 `MATCH path = ...`는 구문 오류입니다. `MATCH p = ...`로 쓰거나 그 이름을
따옴표로 감싸십시오.
```
{#match-compatibility}
## 호환성
{#match-label-expressions-isoiec-39075-168}
### 레이블 표현식 (ISO/IEC 39075 §16.8)
표준의 `