MERGE#
패턴이 이미 있으면 그것을 일치시키고 없으면 만들며, 어느 쪽이든 그 변수를 바인딩합니다.
개요#
[ ON { CREATE | MATCH } SET set_item [, set_item ] ... ] ...
굵게 키워드 · 기울임 직접 채우는 자리 · [ ] 생략 가능 · ... 반복 가능. 구문 표기 규약을 참고하십시오.
설명#
MERGE는 MATCH와 CREATE의 일을 하나의 절이 하는 것입니다. 자기 패턴을
찾고, 그 패턴이 있으면 MATCH처럼 동작하고 없으면 CREATE처럼 동작합니다. 어느 쪽이든 패턴의
변수는 결국 바인딩되므로, 쿼리의 나머지는 둘 중 무엇이 일어났는지 알 필요가 없습니다.
MERGE에 관한 모든 것을 규칙 하나가 결정합니다. 이 절은 패턴 전체를 봅니다:
패턴 전체가 일치하면 아무것도 쓰이지 않습니다.
그중 어느 부분이라도 없으면 패턴 전체가 만들어집니다. 그래프의 다른 곳에 이미 있는 부분까지 포함해서입니다.
a와b는 있고 간선만 없는 상태에서(a)-[:e]->(b)를 merge하면, 간선과 함께 두 번째a와 두 번째b가 만들어집니다.그러므로 이미 무엇이 있는지 확실하지 않을 때는 요소를 하나씩 merge하십시오. 정점마다
MERGE를 쓰고, 그다음 그것들이 바인딩한 변수 사이의 간선에MERGE를 쓰십시오. 그렇게 쓰면MERGE는 멱등합니다.
그 밖의 규칙입니다:
MERGE는 패턴을 정확히 하나 받습니다. 쉼표로 구분한 패턴은 구문 오류입니다.MERGE절을 여러 개 쓰십시오.ON CREATE SET은 패턴이 만들어졌을 때만,ON MATCH SET은 일치했을 때만 실행됩니다. 둘 다 어느 순서로든 줄 수 있고, 각각SET의 항목 목록을 받습니다.패턴 안의 속성도 일치 대상의 일부입니다.
MERGE (m:movie {title: 'Tenet'})는title이 정확히Tenet인movie에만 일치하며,title을 갖고 있기만 한 것에는 일치하지 않습니다.MERGE는 들어오는 행마다 한 번 실행됩니다. 쿼리를 시작하거나, 다른 절 뒤에 오거나, 쿼리를 끝낼 수 있습니다.
매개변수#
예제#
모든 예제는 예제 데이터셋에서 실행됩니다. The last example undoes them.
정점을 만들거나 찾기#
첫 실행은 만듭니다:
MERGE (m:movie {title: 'Tenet'}) RETURN m.title AS film, m.year AS year;
film | year
---------+------
"Tenet" |
(1 row)
패턴에 title만 있었으므로 year는 설정되지 않았습니다. 두 번째 실행은 같은 정점을 찾고
아무것도 쓰지 않습니다:
MERGE (m:movie {title: 'Tenet'}) RETURN m.title AS film, m.year AS year;
film | year
---------+------
"Tenet" |
(1 row)
MATCH (m:movie {title: 'Tenet'}) RETURN count(*) AS rows;
rows
------
1
(1 row)
만들 때와 일치할 때 서로 다른 속성 설정하기#
아무것도 없는 상태에서 시작합니다:
MATCH (m:movie {title: 'Tenet'}) DETACH DELETE m;
UPDATE 1
MERGE (m:movie {title: 'Tenet'})
ON CREATE SET m.year = 2020, m.source = 'created'
ON MATCH SET m.source = 'matched'
RETURN m.title AS film, m.year AS year, m.source AS source;
film | year | source
---------+------+-----------
"Tenet" | 2020 | "created"
(1 row)
똑같은 문장을 두 번째로 실행하면 다른 분기를 탑니다:
MERGE (m:movie {title: 'Tenet'})
ON CREATE SET m.year = 2020, m.source = 'created'
ON MATCH SET m.source = 'matched'
RETURN m.title AS film, m.year AS year, m.source AS source;
film | year | source
---------+------+-----------
"Tenet" | 2020 | "matched"
(1 row)
year는 만들기 분기가 준 값을 그대로 유지합니다. ON MATCH SET이 그것에 손대지 않았기
때문입니다.
패턴 전체를 MERGE하면 정점이 중복되는 것 보기#
Christopher Nolan은 한 명이고, 그는 Tenet을 연출하지 않았습니다:
MATCH (m:movie {title: 'Tenet'}) DETACH DELETE m;
MATCH (p:person {name: 'Christopher Nolan'}) RETURN count(*) AS nolans;
UPDATE 1
nolans
--------
1
(1 row)
경로 전체를 merge하면 간선이 없으므로 일치하는 것을 찾지 못합니다. 그래서 경로 전체를 만듭니다:
MERGE (d:person {name: 'Christopher Nolan'})-[:directed]->(m:movie {title: 'Tenet'})
RETURN d.name AS director, m.title AS film;
director | film
---------------------+---------
"Christopher Nolan" | "Tenet"
(1 row)
MATCH (p:person {name: 'Christopher Nolan'}) RETURN count(*) AS nolans;
nolans
--------
2
(1 row)
born 속성도 없고 원본의 간선도 하나 없는 두 번째 Christopher Nolan입니다. MERGE가 불러들이는
실수가 이것입니다.
대신 요소를 하나씩 merge하기#
그것을 되돌리고, 그다음 요소를 하나씩 따로 merge합니다:
MATCH (p:person {name: 'Christopher Nolan'})
WHERE NOT EXISTS { MATCH (p)-[:directed]->(:movie {title: 'Inception'}) }
DETACH DELETE p;
MATCH (m:movie {title: 'Tenet'}) DETACH DELETE m;
UPDATE 2
UPDATE 1
MERGE (d:person {name: 'Christopher Nolan'})
MERGE (m:movie {title: 'Tenet'})
MERGE (d)-[:directed]->(m)
RETURN d.name AS director, m.title AS film;
director | film
---------------------+---------
"Christopher Nolan" | "Tenet"
(1 row)
MATCH (p:person {name: 'Christopher Nolan'}) RETURN count(*) AS nolans;
nolans
--------
1
(1 row)
첫 MERGE는 이미 있는 사람을 일치시켰고, 둘째는 영화를 만들었고, 셋째는 간선만 만들었습니다. 같은
세 절을 다시 실행해도 아무것도 바뀌지 않습니다:
MATCH (p:person {name: 'Christopher Nolan'})-[:directed]->(m:movie)
RETURN count(*) AS edges;
edges
-------
3
(1 row)
원래 데이터셋의 둘에 merge한 하나를 더한 것이며, 그 문장을 몇 번 실행하든 그대로입니다.
패턴이 둘 이상이면 거부된다#
MERGE (a:movie {title: 'A'}), (b:movie {title: 'B'});
ERROR: syntax error at or near ","
LINE 1: MERGE (a:movie {title: 'A'}), (b:movie {title: 'B'});
^
MERGE 절을 두 개 쓰십시오.
예제 되돌리기#
MATCH (m:movie {title: 'Tenet'}) DETACH DELETE m;
UPDATE 2
참고#
고유성 제약은 중복 위험을 조용한 데이터 오염이 아니라 깔끔한 실패로 바꿔 줍니다. person의
name에 고유성이 걸려 있으면, 위의 패턴 전체 merge는 두 번째 Nolan을 만들 수 없습니다:
CREATE CONSTRAINT unique_person_name ON person ASSERT name IS UNIQUE;
MERGE (d:person {name: 'Christopher Nolan'})-[:directed]->(m:movie {title: 'Tenet'})
RETURN d.name AS director, m.title AS film;
CREATE CONSTRAINT
ERROR: conflicting key value violates exclusion constraint "unique_person_name"
DETAIL: Key ((properties.'name'))=("Christopher Nolan") conflicts with existing key ((properties.'name'))=("Christopher Nolan").
아무것도 만들어지지 않고, 트랜잭션이 그 이유를 보고합니다. merge에 쓰는 키가 무엇이든 그 키에 제약을 선언하십시오.
호환성#
MERGE는 GQL 절이 아니다#
ISO/IEC 39075에는 MERGE가 없습니다. 표준의 데이터 변경 문장은 <insert statement>(§13.2),
<set statement>(§13.3), <remove statement>(§13.4), <delete statement>(§13.5)입니다. MERGE는
Cypher에서 왔고 AgensGraph는 그것을 유지합니다. 표준만으로 같은 일을 하려면
CALL { subquery }를 쓰거나, EXISTS 검사 뒤에
INSERT를 쓰십시오.