Zio.Ontology()
설계서를 만들고, 그 설계서대로 세웁니다. 둘 다 이 묶음입니다 — 앞엣것은 종이를 그리는 일이고, 뒤엣것은 그 종이대로 값을 넣는 일입니다.
설계서에는 어떤 노드에 어떤 속성이 있고 무엇이 무엇과 이어지는지가 적혀 있습니다. 웹의 온톨로지 스키마 에디터에서 그리는 그 종이입니다. IDE 에서 스킬을 짤 때는 화면이 없으니, 여기서 만들고 확인은 나중에 웹에서 합니다.
설계서 만들기 · 고치기
섹션 제목: “설계서 만들기 · 고치기”담당자가 자연어로 업무 흐름을 말하면 그것을 설계서로 옮기는 자리입니다. 좌표·색·내부 식별자는 SDK 가 채우니 뜻만 적으십시오.
from zio_ontology import Zio
got = Zio.ontology.create( title="업무관리", nodes=[ {"name": "Worklog", "title": "업무일지", "display_property": "subject", "properties": [ {"name": "worklog_id", "title": "일지ID", "unique": True, "source": "@worklog_id"}, {"name": "subject", "title": "제목", "source": "@subject"}, ]}, {"name": "Work", "title": "작업", "properties": [ {"name": "work_name", "title": "작업명", "unique": True, "source": "@works.name"}, ]}, ], edges=[{"source": "Worklog", "target": "Work", "rel": "HAS_WORK", "label": "일지의 작업"}],)
tid = got["twin_id"]for w in got["warnings"]: print(w) # 오류가 안 나서 놓치기 쉬운 것들. 담당자에게 그대로 옮기십시오| Method | Description |
|---|---|
Zio.ontology.create(title, nodes, edges) |
설계서를 새로 세우고 twin_id 를 돌려줍니다. nodes·edges 는 안 줘도 되고, 나중에 낱개로 더해도 됩니다. |
Zio.ontology.list() |
설계서 목록. {twin_id, title, status, node_count, edge_count}. |
↓ 여기부터는 설계서 하나를 집어 거는 것들입니다 — 점(.) 앞에 Zio.ontology(twin_id) 가 옵니다. list()·create() 처럼 Zio.ontology. 로 바로 부르지 않습니다. 집는 법은 아래 설계서대로 세우기 절을 보십시오. |
|
Zio.ontology(twin_id).info() |
설계서를 통째로 읽습니다. {twin_id, title, nodes[], edges[], warnings[]}. |
.update(title, description, status) |
설계서의 이름표를 고칩니다. |
.drop() |
설계서를 지웁니다. 이미 쌓인 Neo4j 노드는 보지도 건드리지도 않습니다 — 설계서는 노드를 세울 때 참고하는 종이일 뿐이라, 십만 건이 쌓였다고 종이를 못 지울 이유가 없습니다. |
.add_node(name, title, properties=[], display_property=None) |
노드를 세웁니다. display_property 는 그래프에서 원 안에 뜨는 이름이고 속성 이름 하나를 줍니다. _ 로 시작하는 이름은 다른 트윈의 노드를 가리키는 참조 노드로, 열쇠(PK)만 들고 세웁니다 — 아래 상자를 보십시오. |
.update_node(name, title, description, display_property) |
노드의 이름표를 고칩니다. name 은 못 바꿉니다 — 바꿔도 이미 그 라벨로 쌓인 노드는 안 따라옵니다(설계서는 지나간 데이터에 소급되지 않습니다). rename_node 를 부르면 왜 없고 어떻게 해야 하는지를 담은 AttributeError 가 옵니다 — 이름만 다르게 보이면 되는 것이면 title 을 고치고, 정말로 갈아야 하면 새로 세우고 옛것을 지운 뒤 옛 라벨의 노드를 어떻게 할지는 사람이 정합니다. |
.drop_node(name) |
노드를 지웁니다. 붙어 있던 엣지도 함께 지우고 몇 개였는지 돌려줍니다. 남겨 두면 허공을 가리키는 엣지가 되어 웹에서 화면이 깨집니다. |
.add_property(node, name, title, type, unique, required, source) |
속성 한 칸을 더합니다. unique 와 source 가 무엇인지는 아래 두 상자를 꼭 읽으십시오. |
.update_property(node, name, ...) |
준 칸만 고치고 나머지는 그대로 둡니다. |
.drop_property(node, name) |
속성을 뺍니다. 그것이 display_property 였으면 그 칸도 같이 비웁니다 — 없어진 속성을 가리키는 표시명은 그래프에 빈 원으로 보입니다. |
.add_edge(source, target, rel, label, source_key, target_key) |
노드 둘을 잇습니다. rel 이 Neo4j 에 실제로 서는 관계 이름입니다 — add_edge("Worklog", "Author", "WRITTEN_BY") 는 그래프에 (Worklog)-[:WRITTEN_BY]->(Author) 로 섭니다. label 은 화면에만 쓰는 설명입니다. source_key·target_key 는 어느 속성끼리 맞춰 이을지 정하는 조인 키입니다(여럿이면 목록). |
.drop_edge(source, target, rel=None) |
rel 을 안 주면 그 두 노드 사이의 엣지를 모두 지웁니다. |
언더바(
섹션 제목: “언더바(_) — 다른 트윈의 노드를 가리키는 지름길”_) — 다른 트윈의 노드를 가리키는 지름길설계서를 그리다 다른 트윈 안에 이미 있는 노드(예: 공용
Author·Project)에 이어야 할 때, 그 노드를 여기서 다시 정의하지 않고 이름 앞에_를 붙여 가리킵니다. 화면에서 「이 노드가 저기 있는 노드와 이어진다」를 보여 주는 설계서 위의 표기입니다. 두 규칙만 지키면 됩니다.
- 노드 이름 앞에
_를 붙입니다. (_Author,_Project)- 속성은 열쇠(PK)만 적습니다. 가리키는 데 필요한 건 짝을 맞출 열쇠뿐이라, 나머지 칸은 의미가 없습니다 — 읽기 좋으라고 열쇠 한둘만 남깁니다.
언제
_를 쓰나 — 이 트윈이 그 노드의 값을 (수집으로) 채우는 주인이면 일반 노드로, 이미 다른 트윈이 채우고 있고 당신은 잇기만 하면 될 때_로. 「다른 트윈에 있는지 먼저 찾아볼」 필요는 없습니다 — 같은 이름이 같은 노드라는 보장이 없고, 판단 기준은 존재 여부가 아니라 **「내가 채울 주인인가」**입니다.**「설계서에서는 만들 수 있고, Neo4j 에는 서지 않는다」**가 핵심입니다. 저장할 때
_는 벗겨져 같은 라벨의 그 노드로MERGE됩니다(_Project→ 그래프의Project) — 재정의가 아니라 가리키기라, 열쇠만 들고 와 잇기만 하고 그 노드의 제목·소속·표시명은 덮어쓰지 않습니다. 그래서 실제 insert/update 때_붙은 노드가 새로 생기는 일은 없습니다.Zio.ontology.create(title=“WBS”, nodes=[ {“name”: “Worklog”, “properties”: [ {“name”: “worklog_id”, “unique”: True, “source”: “@id”}]}, {“name”: “_Project”, “properties”: [ # 다른 트윈 노드 참조 (열쇠만) {“name”: “project_code”, “unique”: True, “source”: “@project_code”}]}, ], edges=[{“source”: “Worklog”, “target”: “_Project”, “rel”: “BELONGS_TO”}])
add_node·create로 SDK 에서 바로 만들 수 있습니다 — 웹으로 되돌아가 고칠 필요가 없습니다. 참조 노드의 열쇠에source를 주면 수집 데이터가 그 값을 채워 자동으로 이어지고, 값을 직접 넘길 땐 아래.save()에서_Project에 열쇠만 실어 보냅니다.
섹션 제목: “unique — 같은 노드인지 가르는 열쇠”
unique— 같은 노드인지 가르는 열쇠속성 중 가장 중요한 칸입니다. 이것으로 「이미 있는 그 노드」인지 「새 노드」인지를 가릅니다.
unique 개수 무슨 일이 일어나나 0 개 실행할 때마다 노드가 새로 쌓입니다( MERGE가 아니라CREATE). 오류가 안 나서 몇 주 뒤에야 압니다.1 개 그 값으로 MERGE. 있으면 두고 없으면 만듭니다.2 개 이상 값을 _로 이어 열쇠로 씁니다. 한 칸이라도 비면 그 건은 통째로 안 섭니다.정한 열쇠의 값이 비면 그 건만 건너뜁니다 — 열쇠 없는 유령 노드를 막는 것입니다.
섹션 제목: “source — 어디서 값을 끌어올까”
source— 어디서 값을 끌어올까안 주면 그 속성은 늘 비어 있습니다. 오류는 안 나고 그 칸만 빠진 채 노드가 섭니다.
적는 것 뜻 @issues.title수집 데이터의 issues안의title@worklog_id수집 데이터의 worklog_id그냥 글자 적어 둔 글자가 곧 값 (상수)
@뒤 경로의 앞부분이 배열이면 원소마다 노드가 하나씩 섭니다 —@issues.title에서issues가 셋이면 노드도 셋입니다. 배열을 노드 여럿으로 펴는 유일한 방법입니다.
속성 이름에 쓰면 안 되는 것
섹션 제목: “속성 이름에 쓰면 안 되는 것”노드 속성은 시스템 필드와 한 자리에 평평하게 담깁니다. 그래서 겹치면 시스템 쪽이 이기고, 오류 없이 조용히 어긋납니다. SDK 가 미리 막습니다.
이름 겹치면 id·source·target·labels그래프가 식별자로 씁니다. 연결선이 안 그려집니다 title·twin_id저장할 때 시스템이 덮어씁니다 x·y·z·vx·vy·vz·fx·fy·fz·index·color그래프 화면이 덮어씁니다 _로 시작하는 것시스템 예약입니다( _display)name막지는 않지만, 쓰면 자동 표시명이 그 값으로 고정됩니다
설계서대로 세우기
섹션 제목: “설계서대로 세우기”설계서를 손에 쥐고 그리는 대로 세웁니다. 노드도 엣지도 설계서가 압니다. 스킬은 값만 넘깁니다 — 어느 엣지를 어느 방향으로 걸지는 한 줄도 쓰지 않습니다.
Zio.node().merge() 는 노드 하나를 세웁니다. 엣지는 merge_relation() 으로 직접 걸어야 합니다. 노드가 둘 셋으로 늘고 트리까지 있으면, 산업별 담당자가 설계서를 그려 놓고도 같은 그림을 파이썬으로 또 그리게 됩니다. 그 자리를 이 묶음이 대신합니다.
| Method | Description |
|---|---|
Zio.ontology(twin_id, entry_node=None) |
설계서 한 장을 집습니다. twin_id 는 설계서 uuid 이고, 노드에 twin_id 속성으로 그대로 박히는 값입니다. entry_node 는 뿌리 노드 이름으로, 쓰기에만 필요합니다. |
.save(data) |
설계서에 그려진 대로 노드와 엣지를 세웁니다. data 는 {노드이름: [인스턴스, …]} 입니다. |
두 인자는 에이전트의 「온톨로지 노드 연결」과 같은 것입니다. 에이전트 빌더에서 설계서와 진입 노드를 고르는 그 두 칸이 여기서는 인자가 됩니다.
# 에이전트가 부르는 모양 (수집 경로 — 값을 설계서의 @경로가 끌어온다)execute_ontology_entry("lAOZtMeH", "Worklog", state)
# 스킬이 부르는 모양 (값을 직접 준다)Zio.ontology("tNpBkLim", "WbsItem").save({ "WbsItem": [ {"project_code": "PRJ-0071", "item_name": "GS25 8월 정기점검", "status": "진행중", "progress_pct": 62, "parent_item_name": "GS25 정기점검 3Q"}, {"project_code": "PRJ-0071", "item_name": "GS25 정기점검 3Q", "status": "진행중"}, ], "_Project": [{"project_code": "PRJ-0071"}], "_Work": [{"worklog_id": "weekly_sjlee1_2026_32", "work_name": "8월 정기점검"}],})이 한 번으로 WbsItem 두 개가 서고, REPORT_ON · BELONGS_TO · HAS_SUBTASK 가 함께 걸립니다. 엣지 이야기는 코드에 없습니다.
넘기는 모양
섹션 제목: “넘기는 모양”| 자리 | 규칙 |
|---|---|
| 노드 이름 | 설계서에 적힌 그대로 씁니다. 언더바 접두도 그대로입니다 (_Project). 라벨은 SDK 가 벗겨 냅니다 — 그래프에는 Project 로 들어갑니다. 설계서에 없는 이름은 조용히 무시됩니다. |
| 인스턴스 | 목록이면 원소 하나가 노드 하나입니다. 낱개 dict 도 받습니다. 속성 이름은 설계서의 속성명입니다. |
| 안 넣는 것 | name · _display · title · twin_id 는 SDK 가 붙입니다. 넣으면 계산된 값을 밀어냅니다. |
엣지가 서는 조건
섹션 제목: “엣지가 서는 조건”양쪽을 다 넘겨야 섭니다
섹션 제목: “양쪽을 다 넘겨야 섭니다”엣지는 이번에 넘긴 노드끼리만 걸립니다. 설계서에 그려져 있어도 한쪽을 안 넘기면 그 엣지는 안 섭니다.
# _Project 를 안 넘기면Zio.ontology("tNpBkLim", "WbsItem").save({"WbsItem": [...]})# → WbsItem 은 선다# → WbsItem -[BELONGS_TO]-> Project 는 안 선다# 열쇠만 넘기면 붙는다"_Project": [{"project_code": "PRJ-0071"}]그래서 언더바 접두 노드는 열쇠만 넘깁니다. 이미 있는 노드를 찾아 붙이는 것이 목적이고, 속성은 그 노드를 만든 설계서가 채웁니다. 열쇠만 넘기면 그 노드의 속성은 하나도 안 바뀝니다.
자기 자신을 가리키는 엣지는 설계서가 짝을 짓습니다
섹션 제목: “자기 자신을 가리키는 엣지는 설계서가 짝을 짓습니다”WBS 트리나 선행 작업처럼 같은 노드끼리 잇는 엣지는 설계서의 「키 매핑」이 짝을 정합니다. 스킬은 부모 이름을 속성으로 적어 두기만 하면 됩니다.
엣지 sourceKey targetKey HAS_SUBTASKproject_code, item_nameproject_code, parent_item_namePRECEDESproject_code, item_nameproject_code, previous_item_name가리키는 부모가 아직 없으면 이름만 든 껍데기로 세웁니다. 나중에 그 부모의 값이 들어오면 채워집니다. 트리가 끊기는 것보다 낫다고 보았습니다.
돌려주는 것
섹션 제목: “돌려주는 것”{ "written": True, # 썼는가 "saved": {"WbsItem": 2, "_Project": 1, "_Work": 1}, # 실제로 세운 수 "skipped": [ {"node": "WbsItem", "index": 3, "reason": "열쇠가 비었습니다"}, ], "message": "Data saved successfully to Neo4j.",}saved 는 넘긴 수가 아니라 선 수입니다. 둘이 다르면 skipped 를 보십시오.
written 은 “썼는가” 이지 “성공했는가” 가 아닙니다. 뿌리 열쇠가 비어 아무것도 안 쓴 것은 실패가 아니라 판단입니다 — 값이 안 온 것뿐이고, 그때는 되묻기를 걸 자리입니다.
지켜지는 것
섹션 제목: “지켜지는 것”| 규칙 | 왜 |
|---|---|
| 전부 되거나 전부 안 된다 | 노드와 엣지를 다 만든 뒤 한 번에 실행합니다. 도중에 어긋나면 그래프에는 아무것도 안 쓰입니다. 반쯤 선 그래프가 없습니다. |
| 열쇠가 비면 안 세운다 | 아무도 못 찾는 노드가 생기지 않게 합니다. 그 인스턴스만 건너뛰고 나머지는 그대로 섭니다. |
| 두 번 돌려도 같다 | 열쇠로 찾아 없으면 만들고 있으면 갱신합니다. 같은 값을 다시 넘겨도 노드가 늘지 않습니다. |
| 넘긴 칸만 갱신한다 | 이미 있는 노드에는 이번에 값을 준 칸만 씁니다. 설계서를 고쳐도 지나간 노드를 다시 쓰지 않습니다. |
어느 것을 쓸까
섹션 제목: “어느 것을 쓸까”Zio.node().merge() |
Zio.ontology().save() |
|
|---|---|---|
| 세우는 것 | 노드 하나 | 설계서에 그려진 노드와 엣지 |
| 엣지 | merge_relation() 으로 직접 |
설계서가 안다 |
| 설계서 | 안 본다 | 본다 |
| 쓸 때 | 속성 한 칸 고치기 · 되묻기 반영 | 추론이 만든 것을 통째로 세우기 |
뿌리가 없으면 아무것도 안 씁니다
섹션 제목: “뿌리가 없으면 아무것도 안 씁니다”
entry_node로 준 노드가 이번 데이터의 뿌리입니다. 그 노드의 열쇠가 비어 있으면 저장을 통째로 중단합니다 — 뿌리 없이 가지만 남으면 나중에 아무도 그것을 찾아가지 못합니다. 위 예에서WbsItem을 뿌리로 준 이유가 이것입니다.