MATCH#
GQL 절
그래프에서 패턴이 들어맞는 모든 자리를 찾고, 일치마다 변수 한 행을 바인딩합니다.
개요#
여기서 pattern은 정점 패턴과 간선 패턴을 이어 놓은 것이며, 이름을 붙일 수도 있습니다:
node는 소괄호로 씁니다:
edge는 하이픈 두 개 사이의 대괄호로 쓰고, 그 안에 edge_body를 둡니다:
그 주위의 하이픈과 화살촉이 방향을 나타냅니다. 세 가지가 있습니다:
<-[ edge_body ]- right to left
-[ edge_body ]- either direction
굵게 키워드 · 기울임 직접 채우는 자리 · [ ] 생략 가능 · ... 반복 가능. 구문 표기 규약을 참고하십시오.
설명#
MATCH는 그래프를 읽습니다. 자기 패턴을 저장된 정점과 간선 위에 얹을 수 있는 모든 방식마다 행
하나를 내놓습니다. 패턴의 이름 있는 요소는 각각 그것이 일치시킨 정점·간선·경로에 바인딩됩니다.
파이프라인의 뒤따르는 절이 그 바인딩을 봅니다. 파이프라인 가운데의 MATCH는 들어오는 행마다 한 번
실행되어 자기 일치를 그 행에 조인하며, 관계형 쿼리에서 조인이 행을 더하는 것과 같습니다.
변수가 없는 패턴 요소도 일치됩니다. 뒤에서 그것을 가리킬 수 없을 뿐입니다. 그 요소가 모양을 제약하는 데만 필요하다면 변수를 빼십시오.
레이블은 요소를 그 레이블과 자식 레이블로 제한하고,
ONLY는 그 레이블 자체로 제한합니다. 레이블이 없으면 요소는 그래프의 모든 정점 또는 모든 간선에 일치합니다.패턴 안의 속성 맵은 그것이 적은 키마다 같음을 검사하는 것입니다. 축약형입니다.
(m:movie {year: 1999})와(m:movie) WHERE m.year = 1999는 같은 정점에 일치합니다.쉼표는 하나의
MATCH안에서 독립적인 패턴을 구분합니다. 변수를 공유하는 패턴은 그 변수로 조인되고, 아무것도 공유하지 않는 패턴은 곱집합을 만듭니다.하나의 패턴 일치 안에서 같은 간선을 두 번 쓰지 않습니다. 정점 바인딩은 반복될 수 있어서 패턴이 삼각형을 닫을 수는 있지만, 두 홉 패턴이 자기가 지나온 간선으로 되돌아가는 일은 없습니다.
간선 변수는 패턴마다 한 번만 쓸 수 있습니다. 다시 쓰면
duplicate variable이 나옵니다. 정점 변수는 반복할 수 있고, 그러면 두 자리가 같은 정점으로 제약됩니다.MATCH는 쿼리를 시작하거나 첫 절 뒤 어디에든 놓일 수 있습니다. 쿼리를 끝내지는 않습니다. 쿼리는RETURN,FINISH, 또는 쓰기 절로 끝나야 합니다.
OPTIONAL MATCH는 패턴이 아무것도 찾지 못한 입력 행을 남기고, 그 행을 버리는 대신 패턴의 변수를
null로 바인딩합니다. 그것은 자기 페이지가 있습니다. OPTIONAL MATCH입니다.
매개변수#
- 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를 참고하십시오.
예제#
모든 예제는 예제 데이터셋에서 실행됩니다.
속성으로 정점 하나 찾기#
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 (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 (p:person {name: 'Christopher Nolan'})-[:directed]->(m)
RETURN m.title AS film
ORDER BY film;
film
----------------
"Inception"
"Interstellar"
(2 rows)
간선에는 변수가 없고 먼 쪽 끝점에는 레이블이 없습니다. 둘 다 여전히 일치를 제약하며, 어느 쪽도 바인딩 비용을 들이지 않습니다.
어느 방향이든 간선 일치시키기#
화살촉이 없는 간선 패턴은 간선이 어느 쪽을 가리키든 일치시킵니다:
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]->도 같은 뜻입니다.
경로 전체에 이름 붙이기#
경로 자체를 바인딩하려면 패턴 앞에 variable =을 두십시오:
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 (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인 경로가 포함되므로, 시작 정점도 답 중 하나가 됩니다:
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)
ONLY로 자식 레이블 제외하기#
레이블은 자식 레이블에도 일치합니다. 레이블이 테이블이고 자식 레이블이 그것을 상속하기
때문입니다. ONLY는 일치 범위를 그 레이블 하나로 좁힙니다. 차이를 보려면 person에 자식 레이블을
하나 주십시오:
CREATE VLABEL crew INHERITS (person);
CREATE (:crew {name: 'Bill Pope', born: 1952});
CREATE VLABEL
UPDATE 1
MATCH (p:person) RETURN count(*) AS people;
people
--------
29
(1 row)
MATCH (p:person ONLY) RETURN count(*) AS people;
people
--------
28
(1 row)
ONLY는 레이블 뒤, 속성 맵 앞에 놓입니다. (p:person ONLY {name: 'Keanu Reeves'})처럼입니다.
간선 패턴 -[r:acted_in ONLY]->에서도 같게 동작합니다. 준비한 것은 이렇게 되돌립니다:
MATCH (p:crew) DETACH DELETE p;
DROP VLABEL crew;
UPDATE 1
DROP VLABEL
WHERE로 일치 결과 걸러 내기#
MATCH에 붙인 WHERE는 뒤에 오는 단계가 아니라 그 일치의 일부입니다:
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 (p:person)-[r:acted_in|directed]->(m:movie) RETURN count(r);
ERROR: multiple types for relationship not supported
대신 레이블 없는 간선을 일치시키고 그 레이블을 WHERE에서 검사하십시오:
MATCH (p:person)-[r]->(m:movie)
WHERE label(r) IN ['acted_in', 'directed']
RETURN count(r) AS edges;
edges
-------
46
(1 row)
label()은 요소의 레이블을 문자열로 반환합니다. 그래서 이름 목록에 대한 IN이 일반적인
형태이고, 간선 레이블의 집합에 일치시키는 유일한 방법입니다.
참고#
레이블 검사는 WHERE 안의 콜론이 아니라 label(n) = '...'에 씁니다. WHERE n:movie는 구문
오류이고, 패턴만 조건으로 쓴 것도 그렇습니다. WHERE (m)-[:related_to]->(:movie)는 파싱되지
않습니다. 패턴이 존재하는지 검사하려면
WHERE EXISTS { MATCH (m)-[:related_to]->(:movie) }를 쓰십시오.
속성 맵은 jsonb 값을 비교하고, 속성과의 비교도 그렇습니다. 리터럴의 타입이 저장된 타입과 맞지
않을 때 그것이 문제가 됩니다. WHERE를 참고하십시오.
참고
이름 붙인 경로 변수는 요소 변수보다 좁게 파싱됩니다. (path)는 받아들여지는 정점 변수이지만,
path가 키워드이므로 MATCH path = ...는 구문 오류입니다. MATCH p = ...로 쓰거나 그 이름을
따옴표로 감싸십시오.
호환성#
레이블 표현식 (ISO/IEC 39075 §16.8)#
표준의 <label expression>은 레이블 이름을 논리합은 |, 논리곱은 &, 부정은 !로 엮습니다.
AgensGraph는 패턴 요소마다 레이블 이름 하나만 받으므로 셋 중 어느 것도 쓸 수 없습니다.
-[r:acted_in|directed]->는 multiple types for relationship not supported를 내고,
-[r:acted_in|:directed]->는 구문 오류입니다. openCypher도 논리합을 파이프로 표기하는데, 여기서는
고정 길이 간선, 가변 길이 간선, shortestpath 안에서 모두 거부됩니다. 위에 보인
WHERE label(r) IN [...]을 쓰십시오.
레이블 술어 (ISO/IEC 39075 §19.9)#
표준은 레이블 검사를 n IS LABELED movie 또는 n:movie로 씁니다. AgensGraph는 두 표기 모두 받지
않습니다. label(n) = 'movie'를 쓰십시오.
ONLY 수정자 (ISO/IEC 39075 §16.7)#
표준의 <element pattern filler>는 변수 선언, 레이블 표현식, 조건을 담고 그 밖에는 아무것도
담지 않습니다. ONLY가 없습니다. AgensGraph가 그것을 더한 것은, 여기서 레이블이 자식 레이블이
상속하는 테이블이고 따라서 레이블 일치가 상속 트리 전체에 대한 일치이기 때문입니다.
레이블 상속을 참고하십시오.