Neo4j / / 2026. 1. 12. 18:25

[Neo4j] SET

SET 절(Clause)은 노드(Node)의 레이블(Label)과 노드 및 관계(Relationship)의 속성(Property)을 업데이트하는 데 사용됩니다.

SET 절은 리터럴 또는 매개변수(Parameter)로 제공된 맵(Map)과 함께 사용하여 속성을 설정할 수 있습니다.

참고: 노드에 레이블을 설정하는 것은 멱등(Idempotent) 작업이므로, 이미 해당 레이블을 가진 노드에 레이블을 설정하려고 해도 아무 일도 발생하지 않습니다.
쿼리 통계(Query statistics)는 실제로 업데이트가 발생했는지 여부를 알려줍니다.

예시 그래프

다음 그래프는 아래 예시에서 사용됩니다:

사람들이 KNOWS 관계로 연결된 예시 그래프

이를 재현하려면 비어 있는 Neo4j 데이터베이스에서 다음 쿼리를 실행하세요:

CREATE
  (a:Swedish {name: 'Andy', age: 36, hungry: true}),
  (b {name: 'Stefan'}),
  (c {name: 'Peter', age: 34}),
  (d {name: 'George'}),
  (a)-[:KNOWS]->(c),
  (b)-[:KNOWS]->(a),
  (d)-[:KNOWS]->(c)

속성 설정

노드 속성을 업데이트:

MATCH (n {name: 'Andy'})
SET n.surname = 'Taylor'
RETURN n.name, n.surname

변경된 노드가 쿼리 결과로 반환됩니다.

표 1. 결과

n.name n.surname
"Andy" "Taylor"
행: 1 속성 설정: 1

관계 속성을 업데이트:

MATCH (n:Swedish {name: 'Andy'})-[r:KNOWS]->(m)
SET r.since = 1999
RETURN r, m.name AS friend

표 2. 결과

r friend
[:KNOWS {since: 1999}] "Peter"
행: 1 속성 설정: 1

노드 또는 관계에 더 복잡한 표현식(Expression)을 사용하여 속성을 설정할 수 있습니다.
예를 들어, 노드를 직접 지정하는 것과 달리, 다음 쿼리는 표현식으로 선택된 노드에 속성을 설정하는 방법을 보여줍니다:

MATCH (n {name: 'Andy'})
SET (CASE WHEN n.age = 36 THEN n END).worksIn = 'Malmo'
RETURN n.name, n.worksIn

표 3. 결과

n.name n.worksIn
"Andy" "Malmo"
행: 1 속성 설정: 1

노드 표현식이 null로 평가되면 아무 작업도 수행되지 않으며, 다음 예시가 이를 보여줍니다:

MATCH (n {name: 'Andy'})
SET (CASE WHEN n.age = 55 THEN n END).worksIn = 'Malmo'
RETURN n.name, n.worksIn

어떤 노드도 CASE 표현식과 일치하지 않으므로, 표현식은 null을 반환합니다.
그 결과 업데이트가 발생하지 않으며, 따라서 worksIn 속성도 설정되지 않습니다.

표 4. 결과

n.name n.worksIn
"Andy"
행: 1

속성 업데이트

SET은 노드 또는 관계의 속성을 업데이트하는 데 사용할 수 있습니다.
이 쿼리는 age 속성의 타입(Type)을 강제로 변경합니다:

MATCH (n {name: 'Andy'})
SET n.age = toString(n.age)
RETURN n.name, n.age

age 속성은 STRING '36'으로 변환되었습니다.

표 5. 결과

n.name n.age
"Andy" "36"
행: 1 속성 설정: 1

동적으로 속성 설정 또는 업데이트

SET은 속성 키 이름이 정적으로 알려져 있지 않더라도 노드 또는 관계의 속성을 설정하거나 업데이트하는 데 사용할 수 있습니다.
이는 더 유연한 쿼리를 가능하게 하고 Cypher® 인젝션(Cypher injection) 위험을 완화합니다.
(Cypher 인젝션에 대한 자세한 내용은 Neo4j 지식 베이스(Neo4j Knowledge Base) → Cypher 인젝션 방지(Protecting against Cypher injection)를 참고하세요.)

SET n[key] = expression

동적으로 계산된 키는 STRING 값으로 평가되어야 합니다.
이 쿼리는 노드의 모든 속성 복사본을 생성합니다:

MATCH (n)
FOREACH (k IN keys(n) | SET n[k + "Copy"] = n[k]) (1)
RETURN n.name, keys(n);

| 1 | FOREACH 절은 keys() 함수에서 얻은 각 속성 키 k를 반복합니다.
각 키에 대해 k + "Copy"라는 키 이름으로 노드에 새 속성을 설정하고, 원래 속성의 값을 복사합니다. |
| --- | --- |

이제 노드에는 모든 속성의 복사본이 있습니다.

표 6. 결과

n.name keys(n)
"Andy" ["name", "nameCopy", "age", "ageCopy", "hungry", "hungryCopy"]
"Stefan" ["name", "nameCopy"]
"Peter" ["name", "nameCopy", "age", "ageCopy"]
"George" ["name", "nameCopy"]
행: 4 속성 설정: 6

속성 제거

속성은 보통 REMOVE로 제거하지만, SET 명령으로 제거하는 것이 편리한 경우도 있습니다.
대표적인 경우가 속성이 매개변수로 제공될 때입니다.

MATCH (n {name: 'Andy'})
SET n.name = null
RETURN n.name, n.age

name 속성이 이제 없습니다.

표 7. 결과

n.name n.age
"36"
행: 1 속성 설정: 1

노드와 관계 사이에서 속성 복사

SETproperties() 함수를 사용하여 한 노드 또는 관계의 모든 속성을 다른 노드 또는 관계로 복사할 수 있습니다.
이렇게 하면 복사 대상 노드 또는 관계의 다른 모든 속성이 제거됩니다.

MATCH
  (at {name: 'Andy'}),
  (pn {name: 'Peter'})
SET at = properties(pn)
RETURN at.name, at.age, at.hungry, pn.name, pn.age

'Andy' 노드는 자신의 모든 속성이 'Peter' 노드의 속성으로 교체되었습니다.

표 8. 결과

at.name at.age at.hungry pn.name pn.age
"Peter" 34 "Peter" 34
행: 1 속성 설정: 3

맵과 =를 사용하여 모든 속성 교체

속성 대체 연산자(Operator) =SET과 함께 사용하여 노드 또는 관계의 기존 속성을 맵에서 제공한 값으로 모두 교체할 수 있습니다:

MATCH (p {name: 'Peter'})
SET p = {name: 'Peter Smith', position: 'Entrepreneur'}
RETURN p.name, p.age, p.position

이 쿼리는 name 속성을 Peter에서 Peter Smith로 업데이트하고, age 속성을 삭제하며, 'Peter' 노드에 position 속성을 추가했습니다.

표 9. 결과

p.name p.age p.position
"Peter Smith" "Entrepreneur"
행: 1 속성 설정: 3

빈 맵과 =로 모든 속성 제거

SET=를 사용하고 오른쪽 피연산자에 빈 맵을 지정하면 노드 또는 관계의 모든 기존 속성을 제거할 수 있습니다:

MATCH (p {name: 'Peter'})
SET p = {}
RETURN p.name, p.age

이 쿼리는 'Peter' 노드에서 nameage 등 모든 기존 속성을 제거했습니다.

표 10. 결과

p.name p.age
행: 1 속성 설정: 2

맵과 +=로 특정 속성 변경

속성 변이 연산자 +=SET과 함께 사용하여 맵에서 속성을 세밀하게 변경할 수 있습니다:

맵에 있지만 노드 또는 관계에 없는 속성은 추가됩니다.

맵에 없지만 노드 또는 관계에 있는 속성은 그대로 유지됩니다.

맵과 노드 또는 관계에 모두 있는 속성은 노드 또는 관계에서 교체됩니다.
하지만 맵의 어떤 속성이 null이면 해당 속성은 노드 또는 관계에서 제거됩니다.

MATCH (p {name: 'Peter'})
SET p += {age: 38, hungry: true, position: 'Entrepreneur'}
RETURN p.name, p.age, p.hungry, p.position

이 쿼리는 name 속성을 그대로 유지하고, age 속성을 34에서 38로 업데이트했으며, 'Peter' 노드에 hungryposition 속성을 추가했습니다.

표 11. 결과

p.name p.age p.hungry p.position
"Peter" 38 true "Entrepreneur"
행: 1 속성 설정: 3

속성 대체 연산자 =와는 달리, =의 오른쪽 피연산자로 빈 맵을 제공해도 노드 또는 관계의 기존 속성이 제거되지는 않습니다.
위에서 설명한 의미론에 따라, =에 빈 맵을 전달하면 아무런 효과가 없습니다:

MATCH (p {name: 'Peter'})
SET p += {}
RETURN p.name, p.age

표 12. 결과

p.name p.age
"Peter" 34
행: 1

하나의 SET 절로 여러 속성 설정

쉼표로 구분하여 여러 속성을 한 번에 설정합니다:

MATCH (n {name: 'Andy'})
SET n.position = 'Developer', n.surname = 'Taylor'

표 13. 결과

(빈 결과)
행: 0 속성 설정: 2

매개변수로 속성 설정

매개변수로 속성 값을 설정합니다:

{
  "surname": "Taylor"
}
MATCH (n {name: 'Andy'})
SET n.surname = $surname
RETURN n.name, n.surname

'Andy' 노드에 surname 속성이 추가되었습니다.

표 14. 결과

n.name n.surname
"Andy" "Taylor"
행: 1 속성 설정: 1

매개변수로 모든 속성 설정

이 작업은 노드의 기존 속성을 매개변수가 제공한 새 속성 집합으로 모두 교체합니다.

{
  "props" : {
    "name": "Andy",
    "position": "Developer"
  }
}
MATCH (n {name: 'Andy'})
SET n = $props
RETURN n.name, n.position, n.age, n.hungry

'Andy' 노드의 모든 속성이 props 매개변수의 속성으로 교체되었습니다.

표 15. 결과

n.name n.position n.age n.hungry
"Andy" "Developer"
행: 1 속성 설정: 4

노드에 레이블 설정

SET을 사용하여 노드에 레이블을 설정합니다:

MATCH (n {name: 'Stefan'})
SET n:German
RETURN n.name, labels(n) AS labels

새로 레이블이 지정된 노드가 쿼리 결과로 반환됩니다.

표 16. 결과

n.name labels
"Stefan" ["German"]
행: 1 추가된 레이블: 1

노드 레이블을 동적으로 설정

SET은 레이블이 정적으로 알려져 있지 않더라도 노드에 레이블을 설정할 수 있습니다.

MATCH (n)
SET n:$(<expr>)
MATCH (n:Swedish)
SET n:$(n.name)
RETURN n.name, labels(n) AS labels

새로 레이블이 지정된 노드가 쿼리 결과로 반환됩니다.

표 17. 결과

n.name labels
"Andy" ["Swedish", "Andy"]
행: 1 추가된 레이블: 1

매개변수로 레이블 설정

매개변수로 레이블 값을 설정합니다:

{
  "label": "Danish"
}
MATCH (n {name: 'Stefan'})
SET n:$($label)
RETURN labels(n) AS labels

'Stefan' 노드에 Danish 레이블이 추가되었습니다.

표 18. 결과

labels
['German', 'Danish']
행: 1 추가된 레이블: 1

노드에 여러 레이블 설정

SET으로 노드에 여러 레이블을 설정하고 :로 서로 다른 레이블을 구분합니다:

MATCH (n {name: 'George'})
SET n:Swedish:Bossman
RETURN n.name, labels(n) AS labels

새로 레이블이 지정된 노드가 쿼리 결과로 반환됩니다.

표 19. 결과

n.name labels
"George" ["Swedish","Bossman"]
행: 1 추가된 레이블: 2

노드에 여러 레이블을 동적으로 설정

LIST<STRING>을 사용하거나 :로 각각을 연결하여 여러 레이블을 동적으로 설정할 수 있습니다:

WITH COLLECT { UNWIND range(0,3) AS id RETURN "Label" + id } as labels (1)
MATCH (n {name: 'George'})
SET n:$(labels)
RETURN n.name, labels(n) AS labels
1 COLLECT 서브쿼리는 UNWIND range(0,3) AS id RETURN "Label" + id의 결과를 집계하여 LIST 문자열("Label0", "Label1", "Label2", "Label3")을 생성하고, 이를 labels 변수에 할당합니다.

새로 레이블이 지정된 노드가 쿼리 결과로 반환됩니다.

표 20. 결과

n.name labels
"George" ["Swedish","Bossman", "Label0", "Label1", "Label2", "Label3"]
행: 1 추가된 레이블: 4

매개변수로 여러 레이블 설정

매개변수로 여러 레이블을 설정합니다:

{
  "labels": ["Swedish", "German"]
}
MATCH (n {name: 'Peter'})
SET n:$($labels)
RETURN labels(n) AS labels

'Peter' 노드에 SwedishGerman 레이블이 추가되었습니다.

표 21. 결과

labels
['Swedish', 'German']
행: 1 추가된 레이블: 2

출처: https://neo4j.com/docs/cypher-manual/25/clauses/set/

반응형
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유