MERGE#

패턴이 이미 있으면 그것을 일치시키고 없으면 만들며, 어느 쪽이든 그 변수를 바인딩합니다.

개요#

MERGE pattern
    [ 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는 들어오는 행마다 한 번 실행됩니다. 쿼리를 시작하거나, 다른 절 뒤에 오거나, 쿼리를 끝낼 수 있습니다.

매개변수#

pattern

MATCH 구문의 경로 패턴 하나입니다. 그 안의 모든 속성은 일치 조건이면서, 만들 때는 설정할 속성이기도 합니다.

ON CREATE SET

패턴이 만들어졌을 때만 적용되는 할당입니다.

ON MATCH SET

패턴을 찾았을 때만 적용되는 할당입니다.

set_item

SET 구문의 할당입니다. variable.property = expression, variable = map, variable += map 중 하나입니다.

예제#

모든 예제는 예제 데이터셋에서 실행됩니다. 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를 쓰십시오.

관련 항목#

  • CREATE — 조건 없이 쓰기

  • MATCH — 패턴 구문

  • SET — ON CREATE SET과 ON MATCH SET이 받는 할당 구문

  • DELETE — merge가 만든 것을 지우기