스크림트 정리
This commit is contained in:
66
cypher_scripts/all_paths_analysis.cypher
Normal file
66
cypher_scripts/all_paths_analysis.cypher
Normal file
@@ -0,0 +1,66 @@
|
||||
// All Scenarios Critical Path Comparison Query
|
||||
// Finds the Critical Path (longest duration path) for each scenario
|
||||
// and returns a comparison table.
|
||||
|
||||
// Optional: Parameter for a list of scenario IDs to compare
|
||||
// Example: :scenario_ids => ['linear-process', 'parallel-process', 'what-if-parallel']
|
||||
|
||||
// 1. Get all Scenario IDs (or filter by provided list)
|
||||
MATCH (s:Scenario)
|
||||
WHERE ($scenario_ids IS NULL OR s.id IN $scenario_ids)
|
||||
WITH COLLECT(s.id) AS scenario_ids
|
||||
|
||||
// 2. For each scenario, find its Critical Path duration and cost
|
||||
UNWIND scenario_ids AS current_scenario_id
|
||||
|
||||
// Find start nodes for the current scenario
|
||||
MATCH (start_node:Job)
|
||||
OPTIONAL MATCH (start_node)<-[r_in:PRECEDES {scenario: current_scenario_id}]-()
|
||||
WITH current_scenario_id, start_node, r_in WHERE r_in IS NULL
|
||||
|
||||
// Find end nodes for the current scenario
|
||||
MATCH (end_node:Job)
|
||||
OPTIONAL MATCH (end_node)-[r_out:PRECEDES {scenario: current_scenario_id}]->()
|
||||
WITH current_scenario_id, start_node, end_node, r_out WHERE r_out IS NULL
|
||||
|
||||
// Match all valid paths for the current scenario
|
||||
MATCH path = (start_node)-[rels:PRECEDES*]->(end_node)
|
||||
WHERE ALL(r IN rels WHERE r.scenario = current_scenario_id)
|
||||
|
||||
// For each job in the path, calculate its effective duration and cost
|
||||
WITH current_scenario_id, path, nodes(path) AS jobs_on_path
|
||||
UNWIND jobs_on_path AS job
|
||||
OPTIONAL MATCH (:Scenario {id: current_scenario_id})-[m:MODIFIES]->(job)
|
||||
WITH
|
||||
current_scenario_id,
|
||||
path,
|
||||
COLLECT({
|
||||
name: job.name,
|
||||
bd: job.base_duration,
|
||||
ed: COALESCE(m.new_duration, job.base_duration),
|
||||
ec: COALESCE(m.new_cost, job.base_cost)
|
||||
}) AS job_data
|
||||
|
||||
// Calculate totals for each path
|
||||
WITH
|
||||
current_scenario_id,
|
||||
path,
|
||||
job_data,
|
||||
REDUCE(s = 0, x IN job_data | s + x.ed) AS total_duration,
|
||||
REDUCE(s = 0, x IN job_data | s + x.ec) AS total_cost
|
||||
|
||||
// Find the Critical Path (longest duration) for the current scenario
|
||||
ORDER BY total_duration DESC
|
||||
LIMIT 1
|
||||
|
||||
// Return the critical path details for the current scenario
|
||||
RETURN
|
||||
current_scenario_id AS scenario_id,
|
||||
[j IN job_data | j.name] AS critical_path_jobs,
|
||||
[j IN job_data | j.bd] AS critical_path_base_durations,
|
||||
[j IN job_data | j.ed] AS critical_path_effective_durations,
|
||||
total_duration AS critical_path_total_duration,
|
||||
total_cost AS critical_path_total_cost
|
||||
|
||||
// 3. Order the final comparison table by critical path duration
|
||||
ORDER BY critical_path_total_duration DESC;
|
||||
50
cypher_scripts/create_scenario_SCN04.cypher
Normal file
50
cypher_scripts/create_scenario_SCN04.cypher
Normal file
@@ -0,0 +1,50 @@
|
||||
// 새로운 시나리오 'SCN04' 생성 및 순서 변경
|
||||
|
||||
// 1. 새로운 시나리오 'SCN04' 노드 생성 (SCN01 기반)
|
||||
CREATE (s4:Scenario {id: 'SCN04', name: 'SCN01 순서 변경 시나리오', description: 'SCN01에서 Job 2와 Job 1의 순서를 변경'});
|
||||
|
||||
// 2. SCN01에 포함된 Job들을 SCN04에도 INCLUDES 관계로 연결합니다.
|
||||
MATCH (s1:Scenario {id: 'SCN01'})-[r:INCLUDES]->(j:Job)
|
||||
WITH s1, j
|
||||
MATCH (s4:Scenario {id: 'SCN04'})
|
||||
CREATE (s4)-[:INCLUDES]->(j);
|
||||
|
||||
// 3. SCN01의 순서를 기반으로 SCN04의 초기 순서를 복제합니다.
|
||||
// - STARTS_WITH 관계 복제
|
||||
MATCH (s1:Scenario {id: 'SCN01'})-[sw:STARTS_WITH]->(start_job:Job)
|
||||
WITH s1, start_job
|
||||
MATCH (s4:Scenario {id: 'SCN04'})
|
||||
CREATE (s4)-[:STARTS_WITH]->(start_job);
|
||||
|
||||
// - NEXT 관계망 복제 (SCN04 시나리오에 종속된 NEXT 관계 생성)
|
||||
MATCH (s1:Scenario {id: 'SCN01'})-[:STARTS_WITH]->(start_job:Job)
|
||||
MATCH path = (start_job)-[:NEXT*]->(end_job:Job)
|
||||
WHERE NOT (end_job)-[:NEXT]->()
|
||||
WITH nodes(path) AS jobs
|
||||
UNWIND range(0, size(jobs)-2) AS i
|
||||
WITH jobs[i] AS from_job, jobs[i+1] AS to_job
|
||||
MATCH (s4:Scenario {id: 'SCN04'})
|
||||
// MERGE를 사용하여 SCN04의 Job들을 가져와서 NEXT 관계 생성
|
||||
MERGE (j1:Job {id: from_job.id})
|
||||
MERGE (j2:Job {id: to_job.id})
|
||||
CREATE (j1)-[:NEXT {scenario: 'SCN04'}]->(j2);
|
||||
|
||||
|
||||
// 4. SCN04에서 Job 1과 Job 2의 순서를 변경합니다. (기존 1->2->3 ... 을 2->1->3 ... 으로)
|
||||
// - 기존 관계 삭제: (s4)-[sw:STARTS_WITH]->(j1), (j1)-[n1:NEXT {scenario: 'SCN04'}]->(j2)
|
||||
MATCH (s4:Scenario {id: 'SCN04'})-[sw:STARTS_WITH]->(j1:Job {id: '1'})
|
||||
DELETE sw;
|
||||
|
||||
MATCH (j1:Job {id: '1'})-[n1:NEXT {scenario: 'SCN04'}]->(j2:Job {id: '2'})
|
||||
DELETE n1;
|
||||
|
||||
MATCH (j2:Job {id: '2'})-[n2:NEXT {scenario: 'SCN04'}]->(j3:Job {id: '3'})
|
||||
DELETE n2;
|
||||
|
||||
// - 새로운 관계 생성: (s4)-[:STARTS_WITH]->(j2), (j2)-[:NEXT]->(j1), (j1)-[:NEXT]->(j3)
|
||||
MATCH (s4:Scenario {id: 'SCN04'}), (j1:Job {id: '1'}), (j2:Job {id: '2'}), (j3:Job {id: '3'})
|
||||
CREATE (s4)-[:STARTS_WITH]->(j2),
|
||||
(j2)-[:NEXT {scenario: 'SCN04'}]->(j1),
|
||||
(j1)-[:NEXT {scenario: 'SCN04'}]->(j3);
|
||||
|
||||
RETURN "SCN04가 성공적으로 생성되었습니다.";
|
||||
25
cypher_scripts/create_scenario_delta.cypher
Normal file
25
cypher_scripts/create_scenario_delta.cypher
Normal file
@@ -0,0 +1,25 @@
|
||||
// Query to Create a New Scenario and its Delta (MODIFIES relationship)
|
||||
// This allows defining a new 'what-if' scenario by specifying changes to a job's properties.
|
||||
|
||||
// Parameters:
|
||||
// :new_scenario_id => 'what-if-2'
|
||||
// :description => 'Job 5 기간 단축 시나리오'
|
||||
// :target_job_id => 5
|
||||
// :new_duration_value => 3
|
||||
// :new_cost_value => 50
|
||||
|
||||
// 1. Create the new Scenario node if it doesn't already exist
|
||||
MERGE (s:Scenario {id: $new_scenario_id})
|
||||
ON CREATE SET s.description = $description
|
||||
|
||||
// 2. Find the target Job to modify
|
||||
MATCH (j:Job {id: $target_job_id})
|
||||
|
||||
// 3. Create or update the MODIFIES relationship between the Scenario and the Job
|
||||
// This relationship holds the delta (the new property values for this scenario)
|
||||
MERGE (s)-[m:MODIFIES]->(j)
|
||||
ON CREATE SET m.new_duration = $new_duration_value, m.new_cost = $new_cost_value
|
||||
ON MATCH SET m.new_duration = $new_duration_value, m.new_cost = $new_cost_value
|
||||
|
||||
// 4. Return the created/updated Scenario and the modified Job for confirmation
|
||||
RETURN s, m, j;
|
||||
13
cypher_scripts/create_schema.cypher
Normal file
13
cypher_scripts/create_schema.cypher
Normal file
@@ -0,0 +1,13 @@
|
||||
// Memgraph 데이터 모델 스키마 정의 (인덱스 및 제약 조건)
|
||||
// 이 스크립트는 데이터를 로드하지 않고, 노드 타입별로 고유 키 제약 조건만 설정합니다.
|
||||
// UNIQUE 제약 조건은 자동으로 인덱스를 생성합니다.
|
||||
|
||||
CREATE CONSTRAINT ON (j:Job) ASSERT j.id IS UNIQUE;
|
||||
CREATE CONSTRAINT ON (jt:JobType) ASSERT jt.type_id IS UNIQUE;
|
||||
CREATE CONSTRAINT ON (o:Object) ASSERT o.id IS UNIQUE;
|
||||
CREATE CONSTRAINT ON (ot:ObjectType) ASSERT ot.type_id IS UNIQUE;
|
||||
CREATE CONSTRAINT ON (s:Status) ASSERT s.status_id IS UNIQUE;
|
||||
CREATE CONSTRAINT ON (a:Activity) ASSERT a.id IS UNIQUE;
|
||||
CREATE CONSTRAINT ON (s:Scenario) ASSERT s.id IS UNIQUE;
|
||||
|
||||
RETURN "Schema constraints and indexes created successfully.";
|
||||
58
cypher_scripts/create_schema_only.cypher
Normal file
58
cypher_scripts/create_schema_only.cypher
Normal file
@@ -0,0 +1,58 @@
|
||||
// 1. 인덱스 및 제약 조건 설정
|
||||
CREATE INDEX ON :Job(id);
|
||||
CREATE INDEX ON :JobType(id);
|
||||
CREATE INDEX ON :Object(id);
|
||||
CREATE INDEX ON :ObjectType(id);
|
||||
CREATE INDEX ON :Status(id);
|
||||
CREATE INDEX ON :Activity(id);
|
||||
CREATE INDEX ON :Scenario(id);
|
||||
|
||||
// 2. 노드 레이블 및 관계 타입 정의 (최소한의 샘플 생성)
|
||||
|
||||
// JobType 노드 생성
|
||||
CREATE (:JobType {type_id: 'SAMPLE_JT', name: 'Sample JobType'});
|
||||
|
||||
// Job 노드 생성
|
||||
CREATE (:Job {id: 'SAMPLE_JOB', name: 'Sample Job', duration: 0, cost: 0});
|
||||
|
||||
// ObjectType 노드 생성
|
||||
CREATE (:ObjectType {type_id: 'SAMPLE_OT', name: 'Sample ObjectType'});
|
||||
|
||||
// Object 노드 생성
|
||||
CREATE (:Object {id: 'SAMPLE_OBJ', name: 'Sample Object'});
|
||||
|
||||
// Status 노드 생성
|
||||
CREATE (:Status {status_id: 'SAMPLE_STATUS', name: 'Sample Status'});
|
||||
|
||||
// Activity 노드 생성
|
||||
CREATE (:Activity {id: 'SAMPLE_ACT', name: 'Sample Activity', description: 'Sample Description'});
|
||||
|
||||
// Scenario 노드 생성
|
||||
CREATE (:Scenario {id: 'SAMPLE_SCN', name: 'Sample Scenario', description: 'Sample Description'});
|
||||
|
||||
// 관계 생성 (샘플 노드들을 연결)
|
||||
MATCH (j:Job {id: 'SAMPLE_JOB'}), (jt:JobType {type_id: 'SAMPLE_JT'})
|
||||
CREATE (j)-[:IS_A]->(jt);
|
||||
|
||||
MATCH (o:Object {id: 'SAMPLE_OBJ'}), (ot:ObjectType {type_id: 'SAMPLE_OT'})
|
||||
CREATE (o)-[:IS_A]->(ot);
|
||||
|
||||
MATCH (j1:Job {id: 'SAMPLE_JOB'}), (j2:Job {id: 'SAMPLE_JOB'})
|
||||
CREATE (j1)-[:PRECEDES]->(j2);
|
||||
|
||||
MATCH (j:Job {id: 'SAMPLE_JOB'}), (s:Status {status_id: 'SAMPLE_STATUS'})
|
||||
CREATE (j)-[:HAS_STATUS]->(s);
|
||||
|
||||
MATCH (s:Scenario {id: 'SAMPLE_SCN'}), (j:Job {id: 'SAMPLE_JOB'})
|
||||
CREATE (s)-[:INCLUDES]->(j);
|
||||
|
||||
MATCH (s1:Scenario {id: 'SAMPLE_SCN'}), (s2:Scenario {id: 'SAMPLE_SCN'})
|
||||
CREATE (s1)-[:DELTA_FROM]->(s2);
|
||||
|
||||
MATCH (j:Job {id: 'SAMPLE_JOB'}), (a:Activity {id: 'SAMPLE_ACT'})
|
||||
CREATE (j)-[:PERFORMS]->(a);
|
||||
|
||||
MATCH (a:Activity {id: 'SAMPLE_ACT'}), (o:Object {id: 'SAMPLE_OBJ'})
|
||||
CREATE (a)-[:ACTS_ON]->(o);
|
||||
|
||||
RETURN "Schema creation successful!";
|
||||
29
cypher_scripts/critical_path_analysis.cypher
Normal file
29
cypher_scripts/critical_path_analysis.cypher
Normal file
@@ -0,0 +1,29 @@
|
||||
// Critical Path Analysis Query (Optimized)
|
||||
// Finds the longest path in terms of total duration of jobs.
|
||||
|
||||
// 1. Find all potential start nodes first
|
||||
MATCH (start_node:Job)
|
||||
WHERE NOT EXISTS((:Job)-[:PRECEDES]->(start_node))
|
||||
|
||||
// 2. Find all potential end nodes first
|
||||
MATCH (end_node:Job)
|
||||
WHERE NOT EXISTS((end_node)-[:PRECEDES]->(:Job))
|
||||
|
||||
// 3. Now, match paths ONLY between the pre-filtered start and end nodes
|
||||
MATCH path = (start_node)-[:PRECEDES*]->(end_node)
|
||||
|
||||
// 4. Calculate the total duration for each path
|
||||
WITH
|
||||
path,
|
||||
REDUCE(totalDuration = 0, job IN nodes(path) | totalDuration + job.duration) AS total_duration
|
||||
|
||||
// 5. Return the path and its total duration for visualization
|
||||
RETURN
|
||||
path,
|
||||
total_duration
|
||||
|
||||
// 6. Order by the total duration in descending order to find the longest path
|
||||
ORDER BY total_duration DESC
|
||||
|
||||
// 7. Limit to the top 1 result, which is the Critical Path
|
||||
LIMIT 1;
|
||||
31
cypher_scripts/debug_scenario_SCN04.cypher
Normal file
31
cypher_scripts/debug_scenario_SCN04.cypher
Normal file
@@ -0,0 +1,31 @@
|
||||
// --- SCN04 시나리오 디버깅 쿼리 ---
|
||||
// 아래 쿼리들을 위에서부터 하나씩 **따로따로** 복사하여 Memgraph Lab에서 실행해 보세요.
|
||||
// 각 쿼리가 어떤 결과를 반환하는지 확인하면 문제의 원인을 찾을 수 있습니다.
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// 쿼리 1: SCN04 시나리오 노드가 존재하는지 확인합니다.
|
||||
// 예상 결과: SCN04 노드 1개가 보여야 합니다.
|
||||
// -----------------------------------------------------------------------------
|
||||
MATCH (s:Scenario {id: 'SCN04'})
|
||||
RETURN s;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// 쿼리 2: SCN04에 포함된 Job들이 있는지 확인합니다.
|
||||
// 예상 결과: SCN04 노드와 :INCLUDES 관계로 연결된 5개의 Job 노드가 보여야 합니다.
|
||||
// -----------------------------------------------------------------------------
|
||||
MATCH p = (s:Scenario {id: 'SCN04'})-[:INCLUDES]->(j:Job)
|
||||
RETURN p;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// 쿼리 3: SCN04의 시작 Job이 정의되어 있는지 확인합니다.
|
||||
// 예상 결과: SCN04에서 :STARTS_WITH 관계로 Job '2' 노드가 연결되어 보여야 합니다.
|
||||
// -----------------------------------------------------------------------------
|
||||
MATCH p = (s:Scenario {id: 'SCN04'})-[:STARTS_WITH]->(j:Job)
|
||||
RETURN p;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// 쿼리 4: SCN04의 전체 작업 순서 경로를 확인합니다.
|
||||
// 예상 결과: Job '2' -> Job '1' -> Job '3' -> ... 순서로 :NEXT 관계가 연결되어 보여야 합니다.
|
||||
// -----------------------------------------------------------------------------
|
||||
MATCH p = (s:Scenario {id: 'SCN04'})-[:STARTS_WITH]->(start_job:Job)-[:NEXT* {scenario: 'SCN04'}]->(end_job:Job)
|
||||
RETURN p;
|
||||
38
cypher_scripts/dynamic_cp_analysis.cypher
Normal file
38
cypher_scripts/dynamic_cp_analysis.cypher
Normal file
@@ -0,0 +1,38 @@
|
||||
// Dynamic Critical Path Analysis Query for Graph Visualization (Pure Cypher, Final & Performant)
|
||||
// Collects all paths into a single list to ensure full graph rendering in Memgraph Lab.
|
||||
|
||||
// Parameter for the scenario ID
|
||||
// Example: :scenario_id => 'parallel-process'
|
||||
|
||||
// 1. Find start nodes for the scenario
|
||||
MATCH (start_node:Job)
|
||||
OPTIONAL MATCH (start_node)<-[r_in:PRECEDES {scenario: $scenario_id}]-()
|
||||
WITH start_node, r_in WHERE r_in IS NULL
|
||||
MATCH (end_node:Job)
|
||||
OPTIONAL MATCH (end_node)-[r_out:PRECEDES {scenario: $scenario_id}]->()
|
||||
WITH start_node, end_node, r_out WHERE r_out IS NULL
|
||||
|
||||
// 2. Match all valid paths for the scenario
|
||||
MATCH path = (start_node)-[rels:PRECEDES*]->(end_node)
|
||||
WHERE ALL(r IN rels WHERE r.scenario = $scenario_id)
|
||||
|
||||
// 3. For each job in the path, calculate its effective duration
|
||||
WITH path, nodes(path) AS jobs_on_path
|
||||
UNWIND jobs_on_path AS job
|
||||
OPTIONAL MATCH (:Scenario {id: $scenario_id})-[m:MODIFIES]->(job)
|
||||
WITH
|
||||
path,
|
||||
COLLECT({
|
||||
effective_duration: COALESCE(m.new_duration, job.base_duration)
|
||||
}) AS jobs_with_deltas
|
||||
|
||||
// 4. Calculate total duration for each path
|
||||
WITH
|
||||
path,
|
||||
REDUCE(totalDuration = 0, data IN jobs_with_deltas | totalDuration + data.effective_duration) AS total_duration
|
||||
|
||||
// 5. Collect all paths, ordered by total_duration, into a single list
|
||||
WITH COLLECT({path: path, total_duration: total_duration}) AS paths_with_duration
|
||||
UNWIND paths_with_duration AS p_wd
|
||||
ORDER BY p_wd.total_duration DESC
|
||||
RETURN COLLECT(p_wd.path) AS all_paths;
|
||||
92
cypher_scripts/import.cypher
Normal file
92
cypher_scripts/import.cypher
Normal file
@@ -0,0 +1,92 @@
|
||||
-- 1. (Optional) Clean up the database
|
||||
MATCH (n) DETACH DELETE n;
|
||||
|
||||
-- 2. Create indexes for faster matching
|
||||
CREATE INDEX ON :JobType(id);
|
||||
CREATE INDEX ON :ObjectType(id);
|
||||
CREATE INDEX ON :Job(id);
|
||||
CREATE INDEX ON :Object(id);
|
||||
CREATE INDEX ON :MgmtStatus(id);
|
||||
|
||||
-- 3. Create Nodes from CSV files
|
||||
|
||||
-- Job Types
|
||||
LOAD CSV FROM '/data/job_types.csv' WITH HEADER AS row
|
||||
CREATE (n:JobType {
|
||||
id: row.id,
|
||||
name: row.name,
|
||||
standard_duration: toInteger(row.standard_duration),
|
||||
standard_cost: toInteger(row.standard_cost)
|
||||
});
|
||||
|
||||
-- Object Types
|
||||
LOAD CSV FROM '/data/object_types.csv' WITH HEADER AS row
|
||||
CREATE (n:ObjectType {
|
||||
id: row.id,
|
||||
name: row.name,
|
||||
category: row.category
|
||||
});
|
||||
|
||||
-- Job Instances
|
||||
LOAD CSV FROM '/data/jobs.csv' WITH HEADER AS row
|
||||
CREATE (n:Job {
|
||||
id: toInteger(row.id),
|
||||
name: row.name,
|
||||
duration: toInteger(row.duration),
|
||||
cost: toInteger(row.cost),
|
||||
job_no: row.job_no
|
||||
});
|
||||
|
||||
-- Object Instances
|
||||
LOAD CSV FROM '/data/objects.csv' WITH HEADER AS row
|
||||
CREATE (n:Object {
|
||||
id: row.id,
|
||||
name: row.name,
|
||||
obj_no: row.obj_no
|
||||
});
|
||||
|
||||
-- Management Status Nodes
|
||||
LOAD CSV FROM '/data/mgmt_status.csv' WITH HEADER AS row
|
||||
CREATE (n:MgmtStatus {
|
||||
id: row.id,
|
||||
type: row.type,
|
||||
status: row.status
|
||||
});
|
||||
|
||||
|
||||
-- 4. Create Relationships from relations.csv
|
||||
|
||||
-- Job IS_A JobType
|
||||
LOAD CSV FROM '/data/relations.csv' WITH HEADER AS row
|
||||
WITH row WHERE row.type = 'IS_A' AND toIntegerOrNull(row.from_id) IS NOT NULL
|
||||
MATCH (from:Job {id: toInteger(row.from_id)})
|
||||
MATCH (to:JobType {id: row.to_id})
|
||||
CREATE (from)-[:IS_A]->(to);
|
||||
|
||||
-- Object IS_A ObjectType
|
||||
LOAD CSV FROM '/data/relations.csv' WITH HEADER AS row
|
||||
WITH row WHERE row.type = 'IS_A' AND toIntegerOrNull(row.from_id) IS NULL
|
||||
MATCH (from:Object {id: row.from_id})
|
||||
MATCH (to:ObjectType {id: row.to_id})
|
||||
CREATE (from)-[:IS_A]->(to);
|
||||
|
||||
-- Job PRECEDES Job
|
||||
LOAD CSV FROM '/data/relations.csv' WITH HEADER AS row
|
||||
WITH row WHERE row.type = 'PRECEDES'
|
||||
MATCH (from:Job {id: toInteger(row.from_id)})
|
||||
MATCH (to:Job {id: toInteger(row.to_id)})
|
||||
CREATE (from)-[:PRECEDES]->(to);
|
||||
|
||||
-- Job REQUIRES Object
|
||||
LOAD CSV FROM '/data/relations.csv' WITH HEADER AS row
|
||||
WITH row WHERE row.type = 'REQUIRES'
|
||||
MATCH (from:Job {id: toInteger(row.from_id)})
|
||||
MATCH (to:Object {id: row.to_id})
|
||||
CREATE (from)-[:REQUIRES {quantity: toInteger(row.quantity), unit: row.unit}]->(to);
|
||||
|
||||
-- Job HAS_STATUS MgmtStatus
|
||||
LOAD CSV FROM '/data/relations.csv' WITH HEADER AS row
|
||||
WITH row WHERE row.type = 'HAS_STATUS'
|
||||
MATCH (from:Job {id: toInteger(row.from_id)})
|
||||
MATCH (to:MgmtStatus {id: row.to_id})
|
||||
CREATE (from)-[:HAS_STATUS]->(to);
|
||||
184
cypher_scripts/import_embedded.cypher
Normal file
184
cypher_scripts/import_embedded.cypher
Normal file
@@ -0,0 +1,184 @@
|
||||
-- 1. Clean up the database
|
||||
MATCH (n) DETACH DELETE n;
|
||||
|
||||
-- 2. Create indexes for faster matching
|
||||
CREATE INDEX ON :JobType(id);
|
||||
CREATE INDEX ON :ObjectType(id);
|
||||
CREATE INDEX ON :Job(id);
|
||||
CREATE INDEX ON :Object(id);
|
||||
CREATE INDEX ON :MgmtStatus(id);
|
||||
|
||||
-- 3. Create Nodes with embedded data
|
||||
|
||||
-- Job Types
|
||||
UNWIND [
|
||||
{id: 'JT01', name: '터널 입구 굴착', duration: 10, cost: 150},
|
||||
{id: 'JT02', name: '숏크리트 타설', duration: 5, cost: 80},
|
||||
{id: 'JT03', name: '강지보 설치', duration: 7, cost: 120},
|
||||
{id: 'JT04', name: '방수 및 배수시설 설치', duration: 8, cost: 100},
|
||||
{id: 'JT05', name: '철근 조립', duration: 6, cost: 90},
|
||||
{id: 'JT06', name: '내부 라이닝 콘크리트 타설', duration: 12, cost: 200},
|
||||
{id: 'JT07', name: '조명 및 환기시설 설치', duration: 9, cost: 110},
|
||||
{id: 'JT08', name: '안전시설물 설치', duration: 4, cost: 60},
|
||||
{id: 'JT09', name: '포장 및 차선 도색', duration: 7, cost: 95},
|
||||
{id: 'JT10', name: 'TBM 준비', duration: 15, cost: 500},
|
||||
{id: 'JT11', name: 'TBM 굴진', duration: 30, cost: 1200},
|
||||
{id: 'JT12', name: '세그먼트 조립', duration: 25, cost: 800},
|
||||
{id: 'JT13', name: '그라우팅', duration: 10, cost: 150},
|
||||
{id: 'JT14', name: 'TBM 해체 및 반출', duration: 12, cost: 300},
|
||||
{id: 'JT15', name: '전기/통신 케이블 설치', duration: 8, cost: 130},
|
||||
{id: 'JT16', name: 'CCTV 및 VMS 설치', duration: 5, cost: 70},
|
||||
{id: 'JT17', name: '소방시설 설치', duration: 6, cost: 85},
|
||||
{id: 'JT18', name: '최종 점검', duration: 3, cost: 50},
|
||||
{id: 'JT19', name: '개통 준비', duration: 2, cost: 30}
|
||||
] AS row
|
||||
CREATE (n:JobType {id: row.id, name: row.name, standard_duration: row.duration, standard_cost: row.cost});
|
||||
|
||||
-- Object Types
|
||||
UNWIND [
|
||||
{id: 'OT01', name: '굴착기', category: '장비'},
|
||||
{id: 'OT02', name: '숏크리트 펌프', category: '장비'},
|
||||
{id: 'OT03', name: '강지보재', category: '자재'},
|
||||
{id: 'OT04', name: '방수시트', category: '자재'},
|
||||
{id: 'OT05', name: '콘크리트 믹서', category: '장비'},
|
||||
{id: 'OT06', name: '철근', category: '자재'},
|
||||
{id: 'OT07', name: '조명등', category: '자재'},
|
||||
{id: 'OT08', name: '환풍기', category: '장비'},
|
||||
{id: 'OT09', name: 'TBM', category: '장비'},
|
||||
{id: 'OT10', name: '세그먼트', category: '자재'},
|
||||
{id: 'OT11', name: '그라우트 믹서', category: '장비'},
|
||||
{id: 'OT12', name: '케이블', category: '자재'},
|
||||
{id: 'OT13', name: 'CCTV', category: '장비'},
|
||||
{id: 'OT14', name: '소화기', category: '자재'},
|
||||
{id: 'OT15', name: '차선도색기', category: '장비'},
|
||||
{id: 'OT16', name: '숏크리트', category: '자재'}
|
||||
] AS row
|
||||
CREATE (n:ObjectType {id: row.id, name: row.name, category: row.category});
|
||||
|
||||
-- Job Instances
|
||||
UNWIND [
|
||||
{id: 1, name: '터널 입구 굴착', duration: 10, cost: 150, job_no: 'JOB-001'},
|
||||
{id: 2, name: '1차 숏크리트 타설', duration: 5, cost: 80, job_no: 'JOB-002'},
|
||||
{id: 3, name: '강지보 설치', duration: 7, cost: 120, job_no: 'JOB-003'},
|
||||
{id: 4, name: '2차 숏크리트 타설', duration: 5, cost: 80, job_no: 'JOB-004'},
|
||||
{id: 5, name: '방수 및 배수시설 설치', duration: 8, cost: 100, job_no: 'JOB-005'},
|
||||
{id: 6, name: '철근 조립', duration: 6, cost: 90, job_no: 'JOB-006'},
|
||||
{id: 7, name: '내부 라이닝 콘크리트 타설', duration: 12, cost: 200, job_no: 'JOB-007'},
|
||||
{id: 8, name: '조명 및 환기시설 설치', duration: 9, cost: 110, job_no: 'JOB-008'},
|
||||
{id: 9, name: '안전시설물 설치', duration: 4, cost: 60, job_no: 'JOB-009'},
|
||||
{id: 10, name: '포장 및 차선 도색', duration: 7, cost: 95, job_no: 'JOB-010'},
|
||||
{id: 11, name: 'TBM 준비', duration: 15, cost: 500, job_no: 'JOB-011'},
|
||||
{id: 12, name: 'TBM 굴진', duration: 30, cost: 1200, job_no: 'JOB-012'},
|
||||
{id: 13, name: '세그먼트 조립', duration: 25, cost: 800, job_no: 'JOB-013'},
|
||||
{id: 14, name: '그라우팅', duration: 10, cost: 150, job_no: 'JOB-014'},
|
||||
{id: 15, name: 'TBM 해체 및 반출', duration: 12, cost: 300, job_no: 'JOB-015'},
|
||||
{id: 16, name: '전기/통신 케이블 설치', duration: 8, cost: 130, job_no: 'JOB-016'},
|
||||
{id: 17, name: 'CCTV 및 VMS 설치', duration: 5, cost: 70, job_no: 'JOB-017'},
|
||||
{id: 18, name: '소방시설 설치', duration: 6, cost: 85, job_no: 'JOB-018'},
|
||||
{id: 19, name: '최종 점검', duration: 3, cost: 50, job_no: 'JOB-019'},
|
||||
{id: 20, name: '개통 준비', duration: 2, cost: 30, job_no: 'JOB-020'}
|
||||
] AS row
|
||||
CREATE (n:Job {id: row.id, name: row.name, duration: row.duration, cost: row.cost, job_no: row.job_no});
|
||||
|
||||
-- Object Instances
|
||||
UNWIND [
|
||||
{id: 'OBJ01', name: '굴착기-A01', obj_no: 'EQ-001'},
|
||||
{id: 'OBJ02', name: '숏크리트 펌프-A', obj_no: 'EQ-002'},
|
||||
{id: 'OBJ03', name: '강지보재-L100', obj_no: 'MTR-001'},
|
||||
{id: 'OBJ04', name: '방수시트-S20', obj_no: 'MTR-002'},
|
||||
{id: 'OBJ05', name: '콘크리트 믹서-T1', obj_no: 'EQ-003'},
|
||||
{id: 'OBJ06', name: '철근-D16', obj_no: 'MTR-003'},
|
||||
{id: 'OBJ07', name: '조명등-LED-1', obj_no: 'MTR-004'},
|
||||
{id: 'OBJ08', name: '환풍기-F1', obj_no: 'EQ-004'},
|
||||
{id: 'OBJ09', name: 'TBM-Shield-1', obj_no: 'EQ-005'},
|
||||
{id: 'OBJ10', name: '세그먼트-A타입', obj_no: 'MTR-005'},
|
||||
{id: 'OBJ11', name: '그라우트 믹서-G1', obj_no: 'EQ-006'},
|
||||
{id: 'OBJ12', name: '전원 케이블-HV-1', obj_no: 'MTR-006'},
|
||||
{id: 'OBJ13', name: 'CCTV-001', obj_no: 'EQ-007'},
|
||||
{id: 'OBJ14', name: '소화기-P1', obj_no: 'MTR-007'},
|
||||
{id: 'OBJ15', name: '차선도색기-Y1', obj_no: 'EQ-008'},
|
||||
{id: 'OBJ16', name: '숏크리트-Batch1', obj_no: 'MTR-008'},
|
||||
{id: 'OBJ17', name: '숏크리트-Batch2', obj_no: 'MTR-009'}
|
||||
] AS row
|
||||
CREATE (n:Object {id: row.id, name: row.name, obj_no: row.obj_no});
|
||||
|
||||
-- Management Status Nodes
|
||||
UNWIND [
|
||||
{id: 'CS_APP', type: 'Construction', status: 'APPROVED'},
|
||||
{id: 'CS_CON', type: 'Construction', status: 'CONFIRMED'},
|
||||
{id: 'CS_PLN', type: 'Construction', status: 'PLANNING'},
|
||||
{id: 'PS_EXE', type: 'Project', status: 'EXECUTING'},
|
||||
{id: 'PS_PLN', type: 'Project', status: 'PLANNING'},
|
||||
{id: 'PM_PAID', type: 'Payment', status: 'PAID'},
|
||||
{id: 'PM_APL', type: 'Payment', status: 'APPLIED'},
|
||||
{id: 'PM_NON', type: 'Payment', status: 'NONE'},
|
||||
{id: 'QS_APP', type: 'Quality', status: 'APPROVED'},
|
||||
{id: 'QS_CON', type: 'Quality', status: 'CONFIRMED'},
|
||||
{id: 'QS_PLN', type: 'Quality', status: 'PLANNING'},
|
||||
{id: 'SS_APP', type: 'Safety', status: 'APPROVED'},
|
||||
{id: 'SS_CON', type: 'Safety', status: 'CONFIRMED'},
|
||||
{id: 'SS_PLN', type: 'Safety', status: 'PLANNING'}
|
||||
] AS row
|
||||
CREATE (n:MgmtStatus {id: row.id, type: row.type, status: row.status});
|
||||
|
||||
|
||||
-- 4. Create Relationships
|
||||
|
||||
-- Job IS_A JobType
|
||||
UNWIND [
|
||||
{from: 1, to: 'JT01'}, {from: 2, to: 'JT02'}, {from: 3, to: 'JT03'}, {from: 4, to: 'JT02'}, {from: 5, to: 'JT04'},
|
||||
{from: 6, to: 'JT05'}, {from: 7, to: 'JT06'}, {from: 8, to: 'JT07'}, {from: 9, to: 'JT08'}, {from: 10, to: 'JT09'},
|
||||
{from: 11, to: 'JT10'}, {from: 12, to: 'JT11'}, {from: 13, to: 'JT12'}, {from: 14, to: 'JT13'}, {from: 15, to: 'JT14'},
|
||||
{from: 16, to: 'JT15'}, {from: 17, to: 'JT16'}, {from: 18, to: 'JT17'}, {from: 19, to: 'JT18'}, {from: 20, to: 'JT19'}
|
||||
] AS rel
|
||||
MATCH (from:Job {id: rel.from})
|
||||
MATCH (to:JobType {id: rel.to})
|
||||
CREATE (from)-[:IS_A]->(to);
|
||||
|
||||
-- Object IS_A ObjectType
|
||||
UNWIND [
|
||||
{from: 'OBJ01', to: 'OT01'}, {from: 'OBJ02', to: 'OT02'}, {from: 'OBJ03', to: 'OT03'}, {from: 'OBJ04', to: 'OT04'},
|
||||
{from: 'OBJ05', to: 'OT05'}, {from: 'OBJ06', to: 'OT06'}, {from: 'OBJ07', to: 'OT07'}, {from: 'OBJ08', to: 'OT08'},
|
||||
{from: 'OBJ09', to: 'OT09'}, {from: 'OBJ10', to: 'OT10'}, {from: 'OBJ11', to: 'OT11'}, {from: 'OBJ12', to: 'OT12'},
|
||||
{from: 'OBJ13', to: 'OT13'}, {from: 'OBJ14', to: 'OT14'}, {from: 'OBJ15', to: 'OT15'}, {from: 'OBJ16', to: 'OT16'},
|
||||
{from: 'OBJ17', to: 'OT16'}
|
||||
] AS rel
|
||||
MATCH (from:Object {id: rel.from})
|
||||
MATCH (to:ObjectType {id: rel.to})
|
||||
CREATE (from)-[:IS_A]->(to);
|
||||
|
||||
-- Job PRECEDES Job
|
||||
UNWIND [
|
||||
{from: 1, to: 2}, {from: 2, to: 3}, {from: 3, to: 4}, {from: 4, to: 5}, {from: 5, to: 6}, {from: 6, to: 7},
|
||||
{from: 7, to: 8}, {from: 8, to: 9}, {from: 9, to: 10}, {from: 11, to: 12}, {from: 12, to: 13}, {from: 13, to: 14},
|
||||
{from: 14, to: 12}, {from: 14, to: 15}, {from: 15, to: 16}, {from: 16, to: 17}, {from: 17, to: 18}, {from: 18, to: 19},
|
||||
{from: 19, to: 20}
|
||||
] AS rel
|
||||
MATCH (from:Job {id: rel.from})
|
||||
MATCH (to:Job {id: rel.to})
|
||||
CREATE (from)-[:PRECEDES]->(to);
|
||||
|
||||
-- Job REQUIRES Object
|
||||
UNWIND [
|
||||
{from: 1, to: 'OBJ01', quantity: 1, unit: 'unit'},
|
||||
{from: 2, to: 'OBJ02', quantity: 1, unit: 'unit'},
|
||||
{from: 2, to: 'OBJ16', quantity: 50, unit: 'ton'},
|
||||
{from: 3, to: 'OBJ03', quantity: 100, unit: 'meter'},
|
||||
{from: 4, to: 'OBJ02', quantity: 1, unit: 'unit'},
|
||||
{from: 4, to: 'OBJ17', quantity: 40, unit: 'ton'}
|
||||
] AS rel
|
||||
MATCH (from:Job {id: rel.from})
|
||||
MATCH (to:Object {id: rel.to})
|
||||
CREATE (from)-[:REQUIRES {quantity: rel.quantity, unit: rel.unit}]->(to);
|
||||
|
||||
-- Job HAS_STATUS MgmtStatus
|
||||
UNWIND [
|
||||
{from: 1, to: 'CS_APP'}, {from: 1, to: 'PS_EXE'}, {from: 1, to: 'PM_PAID'}, {from: 1, to: 'QS_APP'}, {from: 1, to: 'SS_APP'},
|
||||
{from: 2, to: 'CS_APP'}, {from: 2, to: 'PS_EXE'}, {from: 2, to: 'PM_PAID'}, {from: 2, to: 'QS_APP'}, {from: 2, to: 'SS_APP'},
|
||||
{from: 3, to: 'CS_CON'}, {from: 3, to: 'PS_EXE'}, {from: 3, to: 'PM_APL'}, {from: 3, to: 'QS_CON'}, {from: 3, to: 'SS_CON'},
|
||||
{from: 4, to: 'CS_PLN'}, {from: 4, to: 'PS_PLN'}, {from: 4, to: 'PM_NON'}, {from: 4, to: 'QS_PLN'}, {from: 4, to: 'SS_PLN'},
|
||||
{from: 5, to: 'CS_PLN'}, {from: 5, to: 'PS_PLN'}, {from: 5, to: 'PM_NON'}, {from: 5, to: 'QS_PLN'}, {from: 5, to: 'SS_PLN'}
|
||||
] AS rel
|
||||
MATCH (from:Job {id: rel.from})
|
||||
MATCH (to:MgmtStatus {id: rel.to})
|
||||
CREATE (from)-[:HAS_STATUS]->(to);
|
||||
183
cypher_scripts/import_embedded_clean.cypher
Normal file
183
cypher_scripts/import_embedded_clean.cypher
Normal file
@@ -0,0 +1,183 @@
|
||||
MATCH (n) DETACH DELETE n;
|
||||
|
||||
CREATE INDEX ON :JobType(id);
|
||||
CREATE INDEX ON :ObjectType(id);
|
||||
CREATE INDEX ON :Job(id);
|
||||
CREATE INDEX ON :Object(id);
|
||||
CREATE INDEX ON :MgmtStatus(id);
|
||||
CREATE INDEX ON :Scenario(id);
|
||||
|
||||
UNWIND [
|
||||
{id: 'JT01', name: '터널 입구 굴착', duration: 10, cost: 150},
|
||||
{id: 'JT02', name: '숏크리트 타설', duration: 5, cost: 80},
|
||||
{id: 'JT03', name: '강지보 설치', duration: 7, cost: 120},
|
||||
{id: 'JT04', name: '방수 및 배수시설 설치', duration: 8, cost: 100},
|
||||
{id: 'JT05', name: '철근 조립', duration: 6, cost: 90},
|
||||
{id: 'JT06', name: '내부 라이닝 콘크리트 타설', duration: 12, cost: 200},
|
||||
{id: 'JT07', name: '조명 및 환기시설 설치', duration: 9, cost: 110},
|
||||
{id: 'JT08', name: '안전시설물 설치', duration: 4, cost: 60},
|
||||
{id: 'JT09', name: '포장 및 차선 도색', duration: 7, cost: 95},
|
||||
{id: 'JT10', name: 'TBM 준비', duration: 15, cost: 500},
|
||||
{id: 'JT11', name: 'TBM 굴진', duration: 30, cost: 1200},
|
||||
{id: 'JT12', name: '세그먼트 조립', duration: 25, cost: 800},
|
||||
{id: 'JT13', name: '그라우팅', duration: 10, cost: 150},
|
||||
{id: 'JT14', name: 'TBM 해체 및 반출', duration: 12, cost: 300},
|
||||
{id: 'JT15', name: '전기/통신 케이블 설치', duration: 8, cost: 130},
|
||||
{id: 'JT16', name: 'CCTV 및 VMS 설치', duration: 5, cost: 70},
|
||||
{id: 'JT17', name: '소방시설 설치', duration: 6, cost: 85},
|
||||
{id: 'JT18', name: '최종 점검', duration: 3, cost: 50},
|
||||
{id: 'JT19', name: '개통 준비', duration: 2, cost: 30}
|
||||
] AS row
|
||||
CREATE (n:JobType {id: row.id, name: row.name, standard_duration: row.duration, standard_cost: row.cost});
|
||||
|
||||
UNWIND [
|
||||
{id: 'OT01', name: '굴착기', category: '장비'},
|
||||
{id: 'OT02', name: '숏크리트 펌프', category: '장비'},
|
||||
{id: 'OT03', name: '강지보재', category: '자재'},
|
||||
{id: 'OT04', name: '방수시트', category: '자재'},
|
||||
{id: 'OT05', name: '콘크리트 믹서', category: '장비'},
|
||||
{id: 'OT06', name: '철근', category: '자재'},
|
||||
{id: 'OT07', name: '조명등', category: '자재'},
|
||||
{id: 'OT08', name: '환풍기', category: '장비'},
|
||||
{id: 'OT09', name: 'TBM', category: '장비'},
|
||||
{id: 'OT10', name: '세그먼트', category: '자재'},
|
||||
{id: 'OT11', name: '그라우트 믹서', category: '장비'},
|
||||
{id: 'OT12', name: '케이블', category: '자재'},
|
||||
{id: 'OT13', name: 'CCTV', category: '장비'},
|
||||
{id: 'OT14', name: '소화기', category: '자재'},
|
||||
{id: 'OT15', name: '차선도색기', category: '장비'},
|
||||
{id: 'OT16', name: '숏크리트', category: '자재'}
|
||||
] AS row
|
||||
CREATE (n:ObjectType {id: row.id, name: row.name, category: row.category});
|
||||
|
||||
UNWIND [
|
||||
{id: 1, name: '터널 입구 굴착', base_duration: 10, base_cost: 150, job_no: 'JOB-001'},
|
||||
{id: 2, name: '1차 숏크리트 타설', base_duration: 5, base_cost: 80, job_no: 'JOB-002'},
|
||||
{id: 3, name: '강지보 설치', base_duration: 7, base_cost: 120, job_no: 'JOB-003'},
|
||||
{id: 4, name: '2차 숏크리트 타설', base_duration: 5, base_cost: 80, job_no: 'JOB-004'},
|
||||
{id: 5, name: '방수 및 배수시설 설치', base_duration: 8, base_cost: 100, job_no: 'JOB-005'},
|
||||
{id: 6, name: '철근 조립', base_duration: 6, base_cost: 90, job_no: 'JOB-006'},
|
||||
{id: 7, name: '내부 라이닝 콘크리트 타설', base_duration: 12, base_cost: 200, job_no: 'JOB-007'},
|
||||
{id: 8, name: '조명 및 환기시설 설치', base_duration: 9, base_cost: 110, job_no: 'JOB-008'},
|
||||
{id: 9, name: '안전시설물 설치', base_duration: 4, base_cost: 60, job_no: 'JOB-009'},
|
||||
{id: 10, name: '포장 및 차선 도색', base_duration: 7, base_cost: 95, job_no: 'JOB-010'},
|
||||
{id: 11, name: 'TBM 준비', base_duration: 15, base_cost: 500, job_no: 'JOB-011'},
|
||||
{id: 12, name: 'TBM 굴진', base_duration: 30, base_cost: 1200, job_no: 'JOB-012'},
|
||||
{id: 13, name: '세그먼트 조립', base_duration: 25, base_cost: 800, job_no: 'JOB-013'},
|
||||
{id: 14, name: '그라우팅', base_duration: 10, base_cost: 150, job_no: 'JOB-014'},
|
||||
{id: 15, name: 'TBM 해체 및 반출', base_duration: 12, base_cost: 300, job_no: 'JOB-015'},
|
||||
{id: 16, name: '전기/통신 케이블 설치', base_duration: 8, base_cost: 130, job_no: 'JOB-016'},
|
||||
{id: 17, name: 'CCTV 및 VMS 설치', base_duration: 5, base_cost: 70, job_no: 'JOB-017'},
|
||||
{id: 18, name: '소방시설 설치', base_duration: 6, base_cost: 85, job_no: 'JOB-018'},
|
||||
{id: 19, name: '최종 점검', base_duration: 3, base_cost: 50, job_no: 'JOB-019'},
|
||||
{id: 20, name: '개통 준비', base_duration: 2, base_cost: 30, job_no: 'JOB-020'}
|
||||
] AS row
|
||||
CREATE (n:Job {id: row.id, name: row.name, base_duration: row.base_duration, base_cost: row.base_cost, job_no: row.job_no});
|
||||
|
||||
UNWIND [
|
||||
{id: 'OBJ01', name: '굴착기-A01', obj_no: 'EQ-001'},
|
||||
{id: 'OBJ02', name: '숏크리트 펌프-A', obj_no: 'EQ-002'},
|
||||
{id: 'OBJ03', name: '강지보재-L100', obj_no: 'MTR-001'},
|
||||
{id: 'OBJ04', name: '방수시트-S20', obj_no: 'MTR-002'},
|
||||
{id: 'OBJ05', name: '콘크리트 믹서-T1', obj_no: 'EQ-003'},
|
||||
{id: 'OBJ06', name: '철근-D16', obj_no: 'MTR-003'},
|
||||
{id: 'OBJ07', name: '조명등-LED-1', obj_no: 'MTR-004'},
|
||||
{id: 'OBJ08', name: '환풍기-F1', obj_no: 'EQ-004'},
|
||||
{id: 'OBJ09', name: 'TBM-Shield-1', obj_no: 'EQ-005'},
|
||||
{id: 'OBJ10', name: '세그먼트-A타입', obj_no: 'MTR-05'},
|
||||
{id: 'OBJ11', name: '그라우트 믹서-G1', obj_no: 'EQ-006'},
|
||||
{id: 'OBJ12', name: '전원 케이블-HV-1', obj_no: 'MTR-006'},
|
||||
{id: 'OBJ13', name: 'CCTV-001', obj_no: 'EQ-007'},
|
||||
{id: 'OBJ14', name: '소화기-P1', obj_no: 'MTR-007'},
|
||||
{id: 'OBJ15', name: '차선도색기-Y1', obj_no: 'EQ-008'},
|
||||
{id: 'OBJ16', name: '숏크리트-Batch1', obj_no: 'MTR-008'},
|
||||
{id: 'OBJ17', name: '숏크리트-Batch2', obj_no: 'MTR-009'}
|
||||
] AS row
|
||||
CREATE (n:Object {id: row.id, name: row.name, obj_no: row.obj_no});
|
||||
|
||||
UNWIND [
|
||||
{id: 'CS_APP', type: 'Construction', status: 'APPROVED'},
|
||||
{id: 'CS_CON', type: 'Construction', status: 'CONFIRMED'},
|
||||
{id: 'CS_PLN', type: 'Construction', status: 'PLANNING'},
|
||||
{id: 'PS_EXE', type: 'Project', status: 'EXECUTING'},
|
||||
{id: 'PS_PLN', type: 'Project', status: 'PLANNING'},
|
||||
{id: 'PM_PAID', type: 'Payment', status: 'PAID'},
|
||||
{id: 'PM_APL', type: 'Payment', status: 'APPLIED'},
|
||||
{id: 'PM_NON', type: 'Payment', status: 'NONE'},
|
||||
{id: 'QS_APP', type: 'Quality', status: 'APPROVED'},
|
||||
{id: 'QS_CON', type: 'Quality', status: 'CONFIRMED'},
|
||||
{id: 'QS_PLN', type: 'Quality', status: 'PLANNING'},
|
||||
{id: 'SS_APP', type: 'Safety', status: 'APPROVED'},
|
||||
{id: 'SS_CON', type: 'Safety', status: 'CONFIRMED'},
|
||||
{id: 'SS_PLN', type: 'Safety', status: 'PLANNING'}
|
||||
] AS row
|
||||
CREATE (n:MgmtStatus {id: row.id, type: row.type, status: row.status});
|
||||
|
||||
// Scenario Nodes
|
||||
UNWIND [
|
||||
{id: 'base', description: '기본 공정 시나리오'},
|
||||
{id: 'what-if-1', description: 'TBM 굴진 지연 가정 시나리오'}
|
||||
] AS row
|
||||
CREATE (n:Scenario {id: row.id, description: row.description});
|
||||
|
||||
// MODIFIES Relationships (for what-if-1 scenario)
|
||||
UNWIND [
|
||||
{scenario_id: 'what-if-1', job_id: 12, new_duration: 50, new_cost: 1500}
|
||||
] AS delta
|
||||
MATCH (s:Scenario {id: delta.scenario_id})
|
||||
MATCH (j:Job {id: delta.job_id})
|
||||
CREATE (s)-[:MODIFIES {new_duration: delta.new_duration, new_cost: delta.new_cost}]->(j);
|
||||
|
||||
UNWIND [
|
||||
{from: 1, to: 'JT01'}, {from: 2, to: 'JT02'}, {from: 3, to: 'JT03'}, {from: 4, to: 'JT02'}, {from: 5, to: 'JT04'},
|
||||
{from: 6, to: 'JT05'}, {from: 7, to: 'JT06'}, {from: 8, to: 'JT07'}, {from: 9, to: 'JT08'}, {from: 10, to: 'JT09'},
|
||||
{from: 11, to: 'JT10'}, {from: 12, to: 'JT11'}, {from: 13, to: 'JT12'}, {from: 14, to: 'JT13'}, {from: 15, to: 'JT14'},
|
||||
{from: 16, to: 'JT15'}, {from: 17, to: 'JT16'}, {from: 18, to: 'JT17'}, {from: 19, to: 'JT18'}, {from: 20, to: 'JT19'}
|
||||
] AS rel
|
||||
MATCH (from:Job {id: rel.from})
|
||||
MATCH (to:JobType {id: rel.to})
|
||||
CREATE (from)-[:IS_A]->(to);
|
||||
|
||||
UNWIND [
|
||||
{from: 'OBJ01', to: 'OT01'}, {from: 'OBJ02', to: 'OT02'}, {from: 'OBJ03', to: 'OT03'}, {from: 'OBJ04', to: 'OT04'},
|
||||
{from: 'OBJ05', to: 'OT05'}, {from: 'OBJ06', to: 'OT06'}, {from: 'OBJ07', to: 'OT07'}, {from: 'OBJ08', to: 'OT08'},
|
||||
{from: 'OBJ09', to: 'OT09'}, {from: 'OBJ10', to: 'OT10'}, {from: 'OBJ11', to: 'OT11'}, {from: 'OBJ12', to: 'OT12'},
|
||||
{from: 'OBJ13', to: 'OT13'}, {from: 'OBJ14', to: 'OT14'}, {from: 'OBJ15', to: 'OT15'}, {from: 'OBJ16', to: 'OT16'},
|
||||
{from: 'OBJ17', to: 'OT16'}
|
||||
] AS rel
|
||||
MATCH (from:Object {id: rel.from})
|
||||
MATCH (to:ObjectType {id: rel.to})
|
||||
CREATE (from)-[:IS_A]->(to);
|
||||
|
||||
UNWIND [
|
||||
{from: 1, to: 2}, {from: 2, to: 3}, {from: 3, to: 4}, {from: 4, to: 5}, {from: 5, to: 6}, {from: 6, to: 7},
|
||||
{from: 7, to: 8}, {from: 8, to: 9}, {from: 9, to: 10}, {from: 11, to: 12}, {from: 12, to: 13}, {from: 13, to: 14},
|
||||
{from: 14, to: 15}, {from: 15, to: 16}, {from: 16, to: 17}, {from: 17, to: 18}, {from: 18, to: 19},
|
||||
{from: 19, to: 20}
|
||||
] AS rel
|
||||
MATCH (from:Job {id: rel.from})
|
||||
MATCH (to:Job {id: rel.to})
|
||||
CREATE (from)-[:PRECEDES]->(to);
|
||||
|
||||
UNWIND [
|
||||
{from: 1, to: 'OBJ01', quantity: 1, unit: 'unit'},
|
||||
{from: 2, to: 'OBJ02', quantity: 1, unit: 'unit'},
|
||||
{from: 2, to: 'OBJ16', quantity: 50, unit: 'ton'},
|
||||
{from: 3, to: 'OBJ03', quantity: 100, unit: 'meter'},
|
||||
{from: 4, to: 'OBJ02', quantity: 1, unit: 'unit'},
|
||||
{from: 4, to: 'OBJ17', quantity: 40, unit: 'ton'}
|
||||
] AS rel
|
||||
MATCH (from:Job {id: rel.from})
|
||||
MATCH (to:Object {id: rel.to})
|
||||
CREATE (from)-[:REQUIRES {quantity: rel.quantity, unit: rel.unit}]->(to);
|
||||
|
||||
UNWIND [
|
||||
{from: 1, to: 'CS_APP'}, {from: 1, to: 'PS_EXE'}, {from: 1, to: 'PM_PAID'}, {from: 1, to: 'QS_APP'}, {from: 1, to: 'SS_APP'},
|
||||
{from: 2, to: 'CS_APP'}, {from: 2, to: 'PS_EXE'}, {from: 2, to: 'PM_PAID'}, {from: 2, to: 'QS_APP'}, {from: 2, to: 'SS_APP'},
|
||||
{from: 3, to: 'CS_CON'}, {from: 3, to: 'PS_EXE'}, {from: 3, to: 'PM_APL'}, {from: 3, to: 'QS_CON'}, {from: 3, to: 'SS_CON'},
|
||||
{from: 4, to: 'CS_PLN'}, {from: 4, to: 'PS_PLN'}, {from: 4, to: 'PM_NON'}, {from: 4, to: 'QS_PLN'}, {from: 4, to: 'SS_PLN'},
|
||||
{from: 5, to: 'CS_PLN'}, {from: 5, to: 'PS_PLN'}, {from: 5, to: 'PM_NON'}, {from: 5, to: 'QS_PLN'}, {from: 5, to: 'SS_PLN'}
|
||||
] AS rel
|
||||
MATCH (from:Job {id: rel.from})
|
||||
MATCH (to:MgmtStatus {id: rel.to})
|
||||
CREATE (from)-[:HAS_STATUS]->(to);
|
||||
88
cypher_scripts/import_generated_data.cypher
Normal file
88
cypher_scripts/import_generated_data.cypher
Normal file
@@ -0,0 +1,88 @@
|
||||
// Comprehensive Data Generation Script
|
||||
// This script deletes all existing data, creates JobTypes from the provided list,
|
||||
// generates multiple Job instances for each type, and wires them into different scenarios.
|
||||
|
||||
// 1. Clean up the database
|
||||
MATCH (n) DETACH DELETE n;
|
||||
|
||||
// 2. Create Indexes
|
||||
CREATE INDEX ON :JobType(id);
|
||||
CREATE INDEX ON :Job(id);
|
||||
CREATE INDEX ON :Scenario(id);
|
||||
|
||||
// 3. Create JobType Nodes from the provided examples
|
||||
UNWIND [
|
||||
{id: 'JOB1', name: '전단면굴착1#제어발파_굴진장3m초과발파'},
|
||||
{id: 'JOB2', name: '막장면1#시공계획서작성'},
|
||||
{id: 'JOB3', name: '막장면1#시공측량'},
|
||||
{id: 'JOB4', name: '막장면1#측점검측'},
|
||||
{id: 'JOB5', name: '막장면1#암판정시행'},
|
||||
{id: 'JOB6', name: '막장면1#천공준비'},
|
||||
{id: 'JOB7', name: '막장면1#막장면천공'},
|
||||
{id: 'JOB8', name: '막장면1#막장면천공시행'},
|
||||
{id: 'JOB9', name: '전단면굴착1#발파준비'},
|
||||
{id: 'JOB10', name: '전단면굴착1#발파작업'},
|
||||
{id: 'JOB11', name: '전단면굴착1#환기시행'},
|
||||
{id: 'JOB12', name: '전단면굴착1#측량및마킹'},
|
||||
{id: 'JOB13', name: '버력1#버력처리'},
|
||||
{id: 'JOB14', name: '버력1#부석정리'},
|
||||
{id: 'JOB15', name: '버력1#버력처리준비'},
|
||||
{id: 'JOB16', name: '버력1#버력처리시행'},
|
||||
{id: 'JOB17', name: '버력1#부석제거뒷정리'},
|
||||
{id: 'JOB18', name: '버력1#운반차입환'},
|
||||
{id: 'JOB19', name: '강섬유보강숏크리트1#본선부설치'},
|
||||
{id: 'JOB20', name: '강섬유보강숏크리트1#뜬돌제거'},
|
||||
{id: 'JOB21', name: '강섬유보강숏크리트1#측량및여굴량확인'},
|
||||
{id: 'JOB22', name: '강섬유보강숏크리트1#Sealing시행'},
|
||||
{id: 'JOB23', name: '강섬유보강숏크리트1_1#본선부설치'},
|
||||
{id: 'JOB24', name: '강섬유보강숏크리트1_1#타설준비'},
|
||||
{id: 'JOB25', name: '강섬유보강숏크리트1_1#바닥정리및면정리'},
|
||||
{id: 'JOB26', name: '강섬유보강숏크리트1_1#뿜어붙이기'},
|
||||
{id: 'JOB27', name: '강섬유보강숏크리트1_1#잔재제거'},
|
||||
{id: 'JOB28', name: '강섬유보강숏크리트1_1#장비점검'},
|
||||
{id: 'JOB29', name: '전단면굴착2#제어발파_굴진장3m초과발파'}
|
||||
] AS jt
|
||||
CREATE (:JobType {id: jt.id, name: jt.name, base_duration: 10 + toInteger(substring(jt.id, 3)), base_cost: 100 + (10 * toInteger(substring(jt.id, 3)))});
|
||||
|
||||
// 4. Create PRECEDES relationships between JobTypes (The "Absolute Rules")
|
||||
UNWIND [
|
||||
{from: 'JOB2', to: 'JOB3'}, {from: 'JOB3', to: 'JOB4'}, {from: 'JOB4', to: 'JOB5'},
|
||||
{from: 'JOB5', to: 'JOB6'}, {from: 'JOB6', to: 'JOB7'}, {from: 'JOB7', to: 'JOB8'},
|
||||
{from: 'JOB8', to: 'JOB9'}, {from: 'JOB9', to: 'JOB10'}, {from: 'JOB10', to: 'JOB11'},
|
||||
{from: 'JOB11', to: 'JOB12'}, {from: 'JOB12', to: 'JOB13'}, {from: 'JOB12', to: 'JOB14'}, // Fork
|
||||
{from: 'JOB14', to: 'JOB15'}, {from: 'JOB15', to: 'JOB16'}, {from: 'JOB16', to: 'JOB17'},
|
||||
{from: 'JOB17', to: 'JOB18'}, {from: 'JOB18', to: 'JOB19'}, {from: 'JOB18', to: 'JOB20'}, // Fork
|
||||
{from: 'JOB20', to: 'JOB21'}, {from: 'JOB21', to: 'JOB22'}, {from: 'JOB22', to: 'JOB23'},
|
||||
{from: 'JOB22', to: 'JOB24'}, // Fork
|
||||
{from: 'JOB24', to: 'JOB25'}, {from: 'JOB25', to: 'JOB26'}, {from: 'JOB26', to: 'JOB27'},
|
||||
{from: 'JOB27', to: 'JOB28'}, {from: 'JOB28', to: 'JOB29'}
|
||||
] AS rel
|
||||
MATCH (from:JobType {id: rel.from}), (to:JobType {id: rel.to})
|
||||
CREATE (from)-[:PRECEDES]->(to);
|
||||
|
||||
// 5. Generate Job Instances (e.g., 2 instances per JobType)
|
||||
MATCH (jt:JobType)
|
||||
UNWIND range(1, 2) AS i
|
||||
CREATE (:Job {
|
||||
id: jt.id + '-' + i,
|
||||
name: jt.name + ' (Instance ' + i + ')',
|
||||
base_duration: jt.base_duration,
|
||||
base_cost: jt.base_cost
|
||||
})-[:IS_A]->(jt);
|
||||
|
||||
// 6. Create Scenarios
|
||||
|
||||
// Scenario A: Simple Linear Process (Always use instance 1)
|
||||
CREATE (:Scenario {id: 'linear-process', description: '단순 순차 공정 시나리오'});
|
||||
MATCH (from_jt:JobType)-[:PRECEDES]->(to_jt:JobType)
|
||||
MATCH (from_j:Job {id: from_jt.id + '-1'}), (to_j:Job {id: to_jt.id + '-1'})
|
||||
CREATE (from_j)-[:PRECEDES {scenario: 'linear-process'}]->(to_j);
|
||||
|
||||
// Scenario B: Parallel Process (Use instance 2 and model forks)
|
||||
CREATE (:Scenario {id: 'parallel-process', description: '병렬 공정 시나리오'});
|
||||
MATCH (from_jt:JobType)-[:PRECEDES]->(to_jt:JobType)
|
||||
MATCH (from_j:Job {id: from_jt.id + '-2'}), (to_j:Job {id: to_jt.id + '-2'})
|
||||
CREATE (from_j)-[:PRECEDES {scenario: 'parallel-process'}]->(to_j);
|
||||
|
||||
// Add a specific modification for a scenario to test delta logic
|
||||
CREATE (:Scenario {id: 'what-if-parallel', description: '병렬 공정 중 JOB16 지연 가정'})-[:MODIFIES {new_duration: 99}]->(:Job {id: 'JOB16-2'});
|
||||
38
cypher_scripts/import_new_model.cypher
Normal file
38
cypher_scripts/import_new_model.cypher
Normal file
@@ -0,0 +1,38 @@
|
||||
// 1. 기존 스키마 제약 조건 모두 삭제
|
||||
DROP CONSTRAINT ON (j:Job) ASSERT j.id IS UNIQUE;
|
||||
DROP CONSTRAINT ON (jt:JobType) ASSERT jt.type_id IS UNIQUE;
|
||||
DROP CONSTRAINT ON (o:Object) ASSERT o.id IS UNIQUE;
|
||||
DROP CONSTRAINT ON (ot:ObjectType) ASSERT ot.type_id IS UNIQUE;
|
||||
DROP CONSTRAINT ON (s:Status) ASSERT s.status_id IS UNIQUE;
|
||||
DROP CONSTRAINT ON (a:Activity) ASSERT a.id IS UNIQUE;
|
||||
DROP CONSTRAINT ON (s:Scenario) ASSERT s.id IS UNIQUE;
|
||||
|
||||
// 2. 인덱스 생성
|
||||
CREATE INDEX ON :Job(id);
|
||||
CREATE INDEX ON :JobType(id);
|
||||
CREATE INDEX ON :Object(id);
|
||||
CREATE INDEX ON :ObjectType(id);
|
||||
CREATE INDEX ON :Status(id);
|
||||
CREATE INDEX ON :Activity(id);
|
||||
CREATE INDEX ON :Scenario(id);
|
||||
|
||||
// 3. 노드 데이터 로드
|
||||
LOAD CSV FROM "/data/job_types.csv" WITH HEADER AS row CREATE (n:JobType {type_id: row.id, name: row.name});
|
||||
LOAD CSV FROM "/data/jobs.csv" WITH HEADER AS row CREATE (n:Job {id: row.id, name: row.name, duration: toInteger(row.duration), cost: toInteger(row.cost)});
|
||||
LOAD CSV FROM "/data/object_types.csv" WITH HEADER AS row CREATE (n:ObjectType {type_id: row.id, name: row.name});
|
||||
LOAD CSV FROM "/data/objects.csv" WITH HEADER AS row CREATE (n:Object {id: row.id, name: row.name});
|
||||
LOAD CSV FROM "/data/mgmt_status.csv" WITH HEADER AS row CREATE (n:Status {status_id: row.id, name: row.status});
|
||||
LOAD CSV FROM "/data/activities.csv" WITH HEADER AS row CREATE (n:Activity {id: row.id, name: row.name, description: row.description});
|
||||
LOAD CSV FROM "/data/scenarios.csv" WITH HEADER AS row CREATE (n:Scenario {id: row.id, name: row.name, description: row.description});
|
||||
|
||||
// 4. 관계 데이터 로드
|
||||
LOAD CSV FROM "/data/relations.csv" WITH HEADER AS row WHERE row.type = 'IS_A' AND row.from_id STARTS WITH 'J' MATCH (from:Job {id: row.from_id}), (to:JobType {type_id: row.to_id}) CREATE (from)-[:IS_A]->(to);
|
||||
LOAD CSV FROM "/data/relations.csv" WITH HEADER AS row WHERE row.type = 'IS_A' AND row.from_id STARTS WITH 'O' MATCH (from:Object {id: row.from_id}), (to:ObjectType {type_id: row.to_id}) CREATE (from)-[:IS_A]->(to);
|
||||
LOAD CSV FROM "/data/relations.csv" WITH HEADER AS row WHERE row.type = 'PRECEDES' MATCH (from:Job {id: row.from_id}), (to:Job {id: row.to_id}) CREATE (from)-[:PRECEDES]->(to);
|
||||
LOAD CSV FROM "/data/relations.csv" WITH HEADER AS row WHERE row.type = 'HAS_STATUS' MATCH (from:Job {id: row.from_id}), (to:Status {status_id: row.to_id}) CREATE (from)-[:HAS_STATUS]->(to);
|
||||
LOAD CSV FROM "/data/relations_new.csv" WITH HEADER AS row WHERE row.type = 'INCLUDES' MATCH (from:Scenario {id: row.from_id}), (to:Job {id: row.to_id}) CREATE (from)-[:INCLUDES]->(to);
|
||||
LOAD CSV FROM "/data/relations_new.csv" WITH HEADER AS row WHERE row.type = 'DELTA_FROM' MATCH (from:Scenario {id: row.from_id}), (to:Scenario {id: row.to_id}) CREATE (from)-[:DELTA_FROM]->(to);
|
||||
LOAD CSV FROM "/data/relations_new.csv" WITH HEADER AS row WHERE row.type = 'PERFORMS' MATCH (from:Job {id: row.from_id}), (to:Activity {id: row.to_id}) CREATE (from)-[:PERFORMS]->(to);
|
||||
LOAD CSV FROM "/data/relations_new.csv" WITH HEADER AS row WHERE row.type = 'ACTS_ON' MATCH (from:Activity {id: row.from_id}), (to:Object {id: row.to_id}) CREATE (from)-[:ACTS_ON]->(to);
|
||||
|
||||
RETURN "Import successful!";
|
||||
198
cypher_scripts/import_with_embedded_data.cypher
Normal file
198
cypher_scripts/import_with_embedded_data.cypher
Normal file
@@ -0,0 +1,198 @@
|
||||
// 0. 데이터베이스 초기화
|
||||
MATCH (n) DETACH DELETE n;
|
||||
|
||||
// 1. 노드 생성
|
||||
|
||||
// JobType 노드
|
||||
CREATE (:JobType {type_id: 'JT01', name: '터널 입구 굴착'});
|
||||
CREATE (:JobType {type_id: 'JT02', name: '숏크리트 타설'});
|
||||
CREATE (:JobType {type_id: 'JT03', name: '강지보 설치'});
|
||||
CREATE (:JobType {type_id: 'JT04', name: '방수 및 배수시설 설치'});
|
||||
CREATE (:JobType {type_id: 'JT05', name: '철근 조립'});
|
||||
CREATE (:JobType {type_id: 'JT06', name: '내부 라이닝 콘크리트 타설'});
|
||||
CREATE (:JobType {type_id: 'JT07', name: '조명 및 환기시설 설치'});
|
||||
CREATE (:JobType {type_id: 'JT08', name: '안전시설물 설치'});
|
||||
CREATE (:JobType {type_id: 'JT09', name: '포장 및 차선 도색'});
|
||||
CREATE (:JobType {type_id: 'JT10', name: 'TBM 준비'});
|
||||
CREATE (:JobType {type_id: 'JT11', name: 'TBM 굴진'});
|
||||
CREATE (:JobType {type_id: 'JT12', name: '세그먼트 조립'});
|
||||
CREATE (:JobType {type_id: 'JT13', name: '그라우팅'});
|
||||
CREATE (:JobType {type_id: 'JT14', name: 'TBM 해체 및 반출'});
|
||||
CREATE (:JobType {type_id: 'JT15', name: '전기/통신 케이블 설치'});
|
||||
CREATE (:JobType {type_id: 'JT16', name: 'CCTV 및 VMS 설치'});
|
||||
CREATE (:JobType {type_id: 'JT17', name: '소방시설 설치'});
|
||||
CREATE (:JobType {type_id: 'JT18', name: '최종 점검'});
|
||||
CREATE (:JobType {type_id: 'JT19', name: '개통 준비'});
|
||||
|
||||
// Job 노드
|
||||
CREATE (:Job {id: '1', name: '터널 입구 굴착', duration: 10, cost: 150});
|
||||
CREATE (:Job {id: '2', name: '1차 숏크리트 타설', duration: 5, cost: 80});
|
||||
CREATE (:Job {id: '3', name: '강지보 설치', duration: 7, cost: 120});
|
||||
CREATE (:Job {id: '4', name: '2차 숏크리트 타설', duration: 5, cost: 80});
|
||||
CREATE (:Job {id: '5', name: '방수 및 배수시설 설치', duration: 8, cost: 100});
|
||||
CREATE (:Job {id: '6', name: '철근 조립', duration: 6, cost: 90});
|
||||
CREATE (:Job {id: '7', name: '내부 라이닝 콘크리트 타설', duration: 12, cost: 200});
|
||||
CREATE (:Job {id: '8', name: '조명 및 환기시설 설치', duration: 9, cost: 110});
|
||||
CREATE (:Job {id: '9', name: '안전시설물 설치', duration: 4, cost: 60});
|
||||
CREATE (:Job {id: '10', name: '포장 및 차선 도색', duration: 7, cost: 95});
|
||||
CREATE (:Job {id: '11', name: 'TBM 준비', duration: 15, cost: 500});
|
||||
CREATE (:Job {id: '12', name: 'TBM 굴진', duration: 30, cost: 1200});
|
||||
CREATE (:Job {id: '13', name: '세그먼트 조립', duration: 25, cost: 800});
|
||||
CREATE (:Job {id: '14', name: '그라우팅', duration: 10, cost: 150});
|
||||
CREATE (:Job {id: '15', name: 'TBM 해체 및 반출', duration: 12, cost: 300});
|
||||
CREATE (:Job {id: '16', name: '전기/통신 케이블 설치', duration: 8, cost: 130});
|
||||
CREATE (:Job {id: '17', name: 'CCTV 및 VMS 설치', duration: 5, cost: 70});
|
||||
CREATE (:Job {id: '18', name: '소방시설 설치', duration: 6, cost: 85});
|
||||
CREATE (:Job {id: '19', name: '최종 점검', duration: 3, cost: 50});
|
||||
CREATE (:Job {id: '20', name: '개통 준비', duration: 2, cost: 30});
|
||||
|
||||
// ObjectType 노드
|
||||
CREATE (:ObjectType {type_id: 'OT01', name: '굴착기'});
|
||||
CREATE (:ObjectType {type_id: 'OT02', name: '숏크리트 펌프'});
|
||||
CREATE (:ObjectType {type_id: 'OT03', name: '강지보재'});
|
||||
CREATE (:ObjectType {type_id: 'OT04', name: '방수시트'});
|
||||
CREATE (:ObjectType {type_id: 'OT05', name: '콘크리트 믹서'});
|
||||
CREATE (:ObjectType {type_id: 'OT06', name: '철근'});
|
||||
CREATE (:ObjectType {type_id: 'OT07', name: '조명등'});
|
||||
CREATE (:ObjectType {type_id: 'OT08', name: '환풍기'});
|
||||
CREATE (:ObjectType {type_id: 'OT09', name: 'TBM'});
|
||||
CREATE (:ObjectType {type_id: 'OT10', name: '세그먼트'});
|
||||
CREATE (:ObjectType {type_id: 'OT11', name: '그라우트 믹서'});
|
||||
CREATE (:ObjectType {type_id: 'OT12', name: '케이블'});
|
||||
CREATE (:ObjectType {type_id: 'OT13', name: 'CCTV'});
|
||||
CREATE (:ObjectType {type_id: 'OT14', name: '소화기'});
|
||||
CREATE (:ObjectType {type_id: 'OT15', name: '차선도색기'});
|
||||
CREATE (:ObjectType {type_id: 'OT16', name: '숏크리트'});
|
||||
|
||||
// Object 노드
|
||||
CREATE (:Object {id: 'OBJ01', name: '굴착기-A01'});
|
||||
CREATE (:Object {id: 'OBJ02', name: '숏크리트 펌프-A'});
|
||||
CREATE (:Object {id: 'OBJ03', name: '강지보재-L100'});
|
||||
CREATE (:Object {id: 'OBJ04', name: '방수시트-S20'});
|
||||
CREATE (:Object {id: 'OBJ05', name: '콘크리트 믹서-T1'});
|
||||
CREATE (:Object {id: 'OBJ06', name: '철근-D16'});
|
||||
CREATE (:Object {id: 'OBJ07', name: '조명등-LED-1'});
|
||||
CREATE (:Object {id: 'OBJ08', name: '환풍기-F1'});
|
||||
CREATE (:Object {id: 'OBJ09', name: 'TBM-Shield-1'});
|
||||
CREATE (:Object {id: 'OBJ10', name: '세그먼트-A타입'});
|
||||
CREATE (:Object {id: 'OBJ11', name: '그라우트 믹서-G1'});
|
||||
CREATE (:Object {id: 'OBJ12', name: '전원 케이블-HV-1'});
|
||||
CREATE (:Object {id: 'OBJ13', name: 'CCTV-001'});
|
||||
CREATE (:Object {id: 'OBJ14', name: '소화기-P1'});
|
||||
CREATE (:Object {id: 'OBJ15', name: '차선도색기-Y1'});
|
||||
CREATE (:Object {id: 'OBJ16', name: '숏크리트-Batch1'});
|
||||
CREATE (:Object {id: 'OBJ17', name: '숏크리트-Batch2'});
|
||||
|
||||
// Status 노드
|
||||
CREATE (:Status {status_id: 'CS_APP', name: 'APPROVED'});
|
||||
CREATE (:Status {status_id: 'CS_CON', name: 'CONFIRMED'});
|
||||
CREATE (:Status {status_id: 'CS_PLN', name: 'PLANNING'});
|
||||
CREATE (:Status {status_id: 'PS_EXE', name: 'EXECUTING'});
|
||||
CREATE (:Status {status_id: 'PS_PLN', name: 'PLANNING'});
|
||||
CREATE (:Status {status_id: 'PM_PAID', name: 'PAID'});
|
||||
CREATE (:Status {status_id: 'PM_APL', name: 'APPLIED'});
|
||||
CREATE (:Status {status_id: 'PM_NON', name: 'NONE'});
|
||||
CREATE (:Status {status_id: 'QS_APP', name: 'APPROVED'});
|
||||
CREATE (:Status {status_id: 'QS_CON', name: 'CONFIRMED'});
|
||||
CREATE (:Status {status_id: 'QS_PLN', name: 'PLANNING'});
|
||||
CREATE (:Status {status_id: 'SS_APP', name: 'APPROVED'});
|
||||
CREATE (:Status {status_id: 'SS_CON', name: 'CONFIRMED'});
|
||||
CREATE (:Status {status_id: 'SS_PLN', name: 'PLANNING'});
|
||||
|
||||
// Activity 노드
|
||||
CREATE (:Activity {id: 'ACT01', name: '굴착 작업', description: '터널 입구 지반 굴착'});
|
||||
CREATE (:Activity {id: 'ACT02', name: '숏크리트 타설 작업', description: '굴착면에 숏크리트 타설하여 안정화'});
|
||||
CREATE (:Activity {id: 'ACT03', name: '강지보 설치 작업', description: '강재 지보를 설치하여 터널 구조 강화'});
|
||||
CREATE (:Activity {id: 'ACT04', name: '방수/배수 작업', description: '방수시트 및 배수시설 설치'});
|
||||
CREATE (:Activity {id: 'ACT05', name: '철근 조립 작업', description: '내부 라이닝을 위한 철근 조립'});
|
||||
|
||||
// Scenario 노드
|
||||
CREATE (:Scenario {id: 'SCN01', name: '기본 시나리오', description: '가장 기본적인 순서의 작업 흐름'});
|
||||
CREATE (:Scenario {id: 'SCN02', name: 'TBM 공법 적용 시나리오', description: 'TBM 장비를 활용한 대체 작업 흐름'});
|
||||
CREATE (:Scenario {id: 'SCN03', name: 'SCN02 증분 시나리오', description: 'SCN02 시나리오에서 일부 작업 순서 변경'});
|
||||
|
||||
// 2. 관계 생성
|
||||
|
||||
// Job IS_A JobType
|
||||
MATCH (j:Job {id: '1'}), (jt:JobType {type_id: 'JT01'}) CREATE (j)-[:IS_A]->(jt);
|
||||
MATCH (j:Job {id: '2'}), (jt:JobType {type_id: 'JT02'}) CREATE (j)-[:IS_A]->(jt);
|
||||
MATCH (j:Job {id: '3'}), (jt:JobType {type_id: 'JT03'}) CREATE (j)-[:IS_A]->(jt);
|
||||
MATCH (j:Job {id: '4'}), (jt:JobType {type_id: 'JT02'}) CREATE (j)-[:IS_A]->(jt);
|
||||
MATCH (j:Job {id: '5'}), (jt:JobType {type_id: 'JT04'}) CREATE (j)-[:IS_A]->(jt);
|
||||
|
||||
// Object IS_A ObjectType
|
||||
MATCH (o:Object {id: 'OBJ01'}), (ot:ObjectType {type_id: 'OT01'}) CREATE (o)-[:IS_A]->(ot);
|
||||
MATCH (o:Object {id: 'OBJ02'}), (ot:ObjectType {type_id: 'OT02'}) CREATE (o)-[:IS_A]->(ot);
|
||||
MATCH (o:Object {id: 'OBJ16'}), (ot:ObjectType {type_id: 'OT16'}) CREATE (o)-[:IS_A]->(ot);
|
||||
MATCH (o:Object {id: 'OBJ17'}), (ot:ObjectType {type_id: 'OT16'}) CREATE (o)-[:IS_A]->(ot);
|
||||
|
||||
// Job PRECEDES Job
|
||||
MATCH (j1:Job {id: '1'}), (j2:Job {id: '2'}) CREATE (j1)-[:PRECEDES]->(j2);
|
||||
MATCH (j1:Job {id: '2'}), (j2:Job {id: '3'}) CREATE (j1)-[:PRECEDES]->(j2);
|
||||
MATCH (j1:Job {id: '3'}), (j2:Job {id: '4'}) CREATE (j1)-[:PRECEDES]->(j2);
|
||||
MATCH (j1:Job {id: '4'}), (j2:Job {id: '5'}) CREATE (j1)-[:PRECEDES]->(j2);
|
||||
|
||||
// Job HAS_STATUS Status
|
||||
MATCH (j:Job {id: '1'}), (s:Status {status_id: 'CS_APP'}) CREATE (j)-[:HAS_STATUS]->(s);
|
||||
MATCH (j:Job {id: '1'}), (s:Status {status_id: 'PS_EXE'}) CREATE (j)-[:HAS_STATUS]->(s);
|
||||
MATCH (j:Job {id: '1'}), (s:Status {status_id: 'PM_PAID'}) CREATE (j)-[:HAS_STATUS]->(s);
|
||||
MATCH (j:Job {id: '1'}), (s:Status {status_id: 'QS_APP'}) CREATE (j)-[:HAS_STATUS]->(s);
|
||||
MATCH (j:Job {id: '1'}), (s:Status {status_id: 'SS_APP'}) CREATE (j)-[:HAS_STATUS]->(s);
|
||||
MATCH (j:Job {id: '2'}), (s:Status {status_id: 'CS_APP'}) CREATE (j)-[:HAS_STATUS]->(s);
|
||||
MATCH (j:Job {id: '2'}), (s:Status {status_id: 'PS_EXE'}) CREATE (j)-[:HAS_STATUS]->(s);
|
||||
MATCH (j:Job {id: '2'}), (s:Status {status_id: 'PM_PAID'}) CREATE (j)-[:HAS_STATUS]->(s);
|
||||
MATCH (j:Job {id: '2'}), (s:Status {status_id: 'QS_APP'}) CREATE (j)-[:HAS_STATUS]->(s);
|
||||
MATCH (j:Job {id: '2'}), (s:Status {status_id: 'SS_APP'}) CREATE (j)-[:HAS_STATUS]->(s);
|
||||
MATCH (j:Job {id: '3'}), (s:Status {status_id: 'CS_CON'}) CREATE (j)-[:HAS_STATUS]->(s);
|
||||
MATCH (j:Job {id: '3'}), (s:Status {status_id: 'PS_EXE'}) CREATE (j)-[:HAS_STATUS]->(s);
|
||||
MATCH (j:Job {id: '3'}), (s:Status {status_id: 'PM_APL'}) CREATE (j)-[:HAS_STATUS]->(s);
|
||||
MATCH (j:Job {id: '3'}), (s:Status {status_id: 'QS_CON'}) CREATE (j)-[:HAS_STATUS]->(s);
|
||||
MATCH (j:Job {id: '3'}), (s:Status {status_id: 'SS_CON'}) CREATE (j)-[:HAS_STATUS]->(s);
|
||||
MATCH (j:Job {id: '4'}), (s:Status {status_id: 'CS_PLN'}) CREATE (j)-[:HAS_STATUS]->(s);
|
||||
MATCH (j:Job {id: '4'}), (s:Status {status_id: 'PS_PLN'}) CREATE (j)-[:HAS_STATUS]->(s);
|
||||
MATCH (j:Job {id: '4'}), (s:Status {status_id: 'PM_NON'}) CREATE (j)-[:HAS_STATUS]->(s);
|
||||
MATCH (j:Job {id: '4'}), (s:Status {status_id: 'QS_PLN'}) CREATE (j)-[:HAS_STATUS]->(s);
|
||||
MATCH (j:Job {id: '4'}), (s:Status {status_id: 'SS_PLN'}) CREATE (j)-[:HAS_STATUS]->(s);
|
||||
MATCH (j:Job {id: '5'}), (s:Status {status_id: 'CS_PLN'}) CREATE (j)-[:HAS_STATUS]->(s);
|
||||
MATCH (j:Job {id: '5'}), (s:Status {status_id: 'PS_PLN'}) CREATE (j)-[:HAS_STATUS]->(s);
|
||||
MATCH (j:Job {id: '5'}), (s:Status {status_id: 'PM_NON'}) CREATE (j)-[:HAS_STATUS]->(s);
|
||||
MATCH (j:Job {id: '5'}), (s:Status {status_id: 'QS_PLN'}) CREATE (j)-[:HAS_STATUS]->(s);
|
||||
MATCH (j:Job {id: '5'}), (s:Status {status_id: 'SS_PLN'}) CREATE (j)-[:HAS_STATUS]->(s);
|
||||
|
||||
// Scenario INCLUDES Job
|
||||
MATCH (s:Scenario {id: 'SCN01'}), (j:Job {id: '1'}) CREATE (s)-[:INCLUDES]->(j);
|
||||
MATCH (s:Scenario {id: 'SCN01'}), (j:Job {id: '2'}) CREATE (s)-[:INCLUDES]->(j);
|
||||
MATCH (s:Scenario {id: 'SCN01'}), (j:Job {id: '3'}) CREATE (s)-[:INCLUDES]->(j);
|
||||
MATCH (s:Scenario {id: 'SCN01'}), (j:Job {id: '4'}) CREATE (s)-[:INCLUDES]->(j);
|
||||
MATCH (s:Scenario {id: 'SCN01'}), (j:Job {id: '5'}) CREATE (s)-[:INCLUDES]->(j);
|
||||
MATCH (s:Scenario {id: 'SCN02'}), (j:Job {id: '11'}) CREATE (s)-[:INCLUDES]->(j);
|
||||
MATCH (s:Scenario {id: 'SCN02'}), (j:Job {id: '12'}) CREATE (s)-[:INCLUDES]->(j);
|
||||
MATCH (s:Scenario {id: 'SCN02'}), (j:Job {id: '13'}) CREATE (s)-[:INCLUDES]->(j);
|
||||
MATCH (s:Scenario {id: 'SCN02'}), (j:Job {id: '14'}) CREATE (s)-[:INCLUDES]->(j);
|
||||
MATCH (s:Scenario {id: 'SCN02'}), (j:Job {id: '15'}) CREATE (s)-[:INCLUDES]->(j);
|
||||
MATCH (s:Scenario {id: 'SCN03'}), (j:Job {id: '11'}) CREATE (s)-[:INCLUDES]->(j);
|
||||
MATCH (s:Scenario {id: 'SCN03'}), (j:Job {id: '13'}) CREATE (s)-[:INCLUDES]->(j);
|
||||
MATCH (s:Scenario {id: 'SCN03'}), (j:Job {id: '12'}) CREATE (s)-[:INCLUDES]->(j);
|
||||
MATCH (s:Scenario {id: 'SCN03'}), (j:Job {id: '14'}) CREATE (s)-[:INCLUDES]->(j);
|
||||
MATCH (s:Scenario {id: 'SCN03'}), (j:Job {id: '15'}) CREATE (s)-[:INCLUDES]->(j);
|
||||
|
||||
// Scenario DELTA_FROM Scenario
|
||||
MATCH (s1:Scenario {id: 'SCN03'}), (s2:Scenario {id: 'SCN02'}) CREATE (s1)-[:DELTA_FROM]->(s2);
|
||||
|
||||
// Job PERFORMS Activity
|
||||
MATCH (j:Job {id: '1'}), (a:Activity {id: 'ACT01'}) CREATE (j)-[:PERFORMS]->(a);
|
||||
MATCH (j:Job {id: '2'}), (a:Activity {id: 'ACT02'}) CREATE (j)-[:PERFORMS]->(a);
|
||||
MATCH (j:Job {id: '3'}), (a:Activity {id: 'ACT03'}) CREATE (j)-[:PERFORMS]->(a);
|
||||
MATCH (j:Job {id: '4'}), (a:Activity {id: 'ACT02'}) CREATE (j)-[:PERFORMS]->(a);
|
||||
MATCH (j:Job {id: '5'}), (a:Activity {id: 'ACT04'}) CREATE (j)-[:PERFORMS]->(a);
|
||||
MATCH (j:Job {id: '6'}), (a:Activity {id: 'ACT05'}) CREATE (j)-[:PERFORMS]->(a);
|
||||
|
||||
// Activity ACTS_ON Object
|
||||
MATCH (a:Activity {id: 'ACT01'}), (o:Object {id: 'OBJ01'}) CREATE (a)-[:ACTS_ON]->(o);
|
||||
MATCH (a:Activity {id: 'ACT02'}), (o:Object {id: 'OBJ02'}) CREATE (a)-[:ACTS_ON]->(o);
|
||||
MATCH (a:Activity {id: 'ACT02'}), (o:Object {id: 'OBJ16'}) CREATE (a)-[:ACTS_ON]->(o);
|
||||
MATCH (a:Activity {id: 'ACT03'}), (o:Object {id: 'OBJ03'}) CREATE (a)-[:ACTS_ON]->(o);
|
||||
MATCH (a:Activity {id: 'ACT04'}), (o:Object {id: 'OBJ04'}) CREATE (a)-[:ACTS_ON]->(o);
|
||||
MATCH (a:Activity {id: 'ACT05'}), (o:Object {id: 'OBJ06'}) CREATE (a)-[:ACTS_ON]->(o);
|
||||
|
||||
RETURN "All data imported successfully!";
|
||||
57
cypher_scripts/path_analysis_table.cypher
Normal file
57
cypher_scripts/path_analysis_table.cypher
Normal file
@@ -0,0 +1,57 @@
|
||||
// Path Analysis Query for Table View (Pure Cypher, Final & Performant)
|
||||
// Calculates and returns path data in a clear, tabular format for a specific scenario.
|
||||
|
||||
// Parameter for the scenario ID
|
||||
// Example: :scenario_id => 'parallel-process'
|
||||
|
||||
// 1. Find start nodes for the scenario using OPTIONAL MATCH
|
||||
MATCH (start_node:Job)
|
||||
OPTIONAL MATCH (start_node)<-[r_in:PRECEDES {scenario: $scenario_id}]-()
|
||||
WITH start_node, r_in
|
||||
WHERE r_in IS NULL
|
||||
|
||||
// 2. Find end nodes for the scenario using OPTIONAL MATCH
|
||||
MATCH (end_node:Job)
|
||||
OPTIONAL MATCH (end_node)-[r_out:PRECEDES {scenario: $scenario_id}]->()
|
||||
WITH start_node, end_node, r_out
|
||||
WHERE r_out IS NULL
|
||||
|
||||
// 3. Match paths and filter relationships efficiently using WHERE ALL
|
||||
MATCH path = (start_node)-[rels:PRECEDES*]->(end_node)
|
||||
WHERE ALL(r IN rels WHERE r.scenario = $scenario_id)
|
||||
|
||||
// 4. For each job in the path, calculate its effective duration and cost
|
||||
WITH path, nodes(path) AS jobs_on_path
|
||||
UNWIND jobs_on_path AS job
|
||||
OPTIONAL MATCH (:Scenario {id: $scenario_id})-[m:MODIFIES]->(job)
|
||||
WITH
|
||||
path,
|
||||
job,
|
||||
COALESCE(m.new_duration, job.base_duration) AS effective_duration,
|
||||
COALESCE(m.new_cost, job.base_cost) AS effective_cost
|
||||
|
||||
// 5. Group by path and aggregate the pre-calculated effective values
|
||||
WITH
|
||||
path,
|
||||
COLLECT({
|
||||
name: job.name,
|
||||
bd: job.base_duration,
|
||||
ed: effective_duration,
|
||||
ec: effective_cost
|
||||
}) AS job_data
|
||||
WITH
|
||||
path,
|
||||
job_data,
|
||||
REDUCE(s = 0, x IN job_data | s + x.ed) AS total_duration,
|
||||
REDUCE(s = 0, x IN job_data | s + x.ec) AS total_cost
|
||||
|
||||
// 6. Return the calculated data for a clean table view
|
||||
RETURN
|
||||
[j IN job_data | j.name] AS path_jobs,
|
||||
[j IN job_data | j.bd] AS base_durations,
|
||||
[j IN job_data | j.ed] AS effective_durations,
|
||||
total_duration,
|
||||
total_cost
|
||||
|
||||
// 7. Order by duration
|
||||
ORDER BY total_duration DESC;
|
||||
52
cypher_scripts/recreate_scenario_SCN04_final_fix.cypher
Normal file
52
cypher_scripts/recreate_scenario_SCN04_final_fix.cypher
Normal file
@@ -0,0 +1,52 @@
|
||||
// --- SCN04 시나리오 재생성 (최종 수정 쿼리) ---
|
||||
|
||||
// 0. 기존에 잘못 생성되었을 수 있는 SCN04 관련 데이터를 모두 삭제합니다.
|
||||
MATCH (s:Scenario {id: 'SCN04'})
|
||||
DETACH DELETE s;
|
||||
|
||||
// 1. 새로운 시나리오 'SCN04' 노드를 생성하고, WITH 절로 s4 변수를 바로 다음 쿼리로 전달합니다.
|
||||
CREATE (s4:Scenario {id: 'SCN04', name: 'SCN01 순서 변경 시나리오', description: 'SCN01에서 Job 2와 Job 1의 순서를 변경'})
|
||||
WITH s4;
|
||||
|
||||
// 2. SCN01에 포함된 Job들을 찾아 SCN04에 :INCLUDES 관계로 연결합니다.
|
||||
MATCH (s1:Scenario {id: 'SCN01'})-[:INCLUDES]->(j:Job)
|
||||
WITH s4, j // 이전 단계의 s4와 현재 찾은 j를 함께 전달합니다.
|
||||
CREATE (s4)-[:INCLUDES]->(j);
|
||||
|
||||
// 3. SCN01의 순서를 기반으로 SCN04의 초기 순서를 복제합니다.
|
||||
// - STARTS_WITH 관계 복제
|
||||
MATCH (s4:Scenario {id: 'SCN04'})
|
||||
MATCH (s1:Scenario {id: 'SCN01'})-[sw:STARTS_WITH]->(start_job:Job)
|
||||
CREATE (s4)-[:STARTS_WITH]->(start_job);
|
||||
|
||||
// - NEXT 관계망 복제 (SCN04 시나리오에 종속된 NEXT 관계 생성)
|
||||
MATCH (s1:Scenario {id: 'SCN01'})-[:STARTS_WITH]->(start_job:Job)
|
||||
MATCH path = (start_job)-[:NEXT*]->(end_job:Job)
|
||||
WHERE NOT (end_job)-[:NEXT]->()
|
||||
WITH nodes(path) AS jobs
|
||||
UNWIND range(0, size(jobs)-2) AS i
|
||||
WITH jobs[i] AS from_job, jobs[i+1] AS to_job
|
||||
MATCH (s4:Scenario {id: 'SCN04'})
|
||||
MERGE (j1:Job {id: from_job.id})
|
||||
MERGE (j2:Job {id: to_job.id})
|
||||
CREATE (j1)-[:NEXT {scenario: 'SCN04'}]->(j2);
|
||||
|
||||
|
||||
// 4. SCN04에서 Job 1과 Job 2의 순서를 변경합니다. (기존 1->2->3 ... 을 2->1->3 ... 으로)
|
||||
// - 기존 관계 삭제
|
||||
MATCH (s4:Scenario {id: 'SCN04'})-[sw:STARTS_WITH]->(j1:Job {id: '1'})
|
||||
DELETE sw;
|
||||
|
||||
MATCH (j1:Job {id: '1'})-[n1:NEXT {scenario: 'SCN04'}]->(j2:Job {id: '2'})
|
||||
DELETE n1;
|
||||
|
||||
MATCH (j2:Job {id: '2'})-[n2:NEXT {scenario: 'SCN04'}]->(j3:Job {id: '3'})
|
||||
DELETE n2;
|
||||
|
||||
// - 새로운 관계 생성
|
||||
MATCH (s4:Scenario {id: 'SCN04'}), (j1:Job {id: '1'}), (j2:Job {id: '2'}), (j3:Job {id: '3'})
|
||||
CREATE (s4)-[:STARTS_WITH]->(j2),
|
||||
(j2)-[:NEXT {scenario: 'SCN04'}]->(j1),
|
||||
(j1)-[:NEXT {scenario: 'SCN04'}]->(j3);
|
||||
|
||||
RETURN "SCN04가 성공적으로 재생성되었습니다.";
|
||||
52
cypher_scripts/recreate_scenario_SCN04_fix.cypher
Normal file
52
cypher_scripts/recreate_scenario_SCN04_fix.cypher
Normal file
@@ -0,0 +1,52 @@
|
||||
// --- SCN04 시나리오 재생성 (수정된 쿼리) ---
|
||||
|
||||
// 0. 기존에 잘못 생성되었을 수 있는 SCN04 관련 데이터를 모두 삭제합니다.
|
||||
MATCH (s:Scenario {id: 'SCN04'})
|
||||
DETACH DELETE s;
|
||||
|
||||
// 1. 새로운 시나리오 'SCN04' 노드를 다시 생성합니다.
|
||||
CREATE (s4:Scenario {id: 'SCN04', name: 'SCN01 순서 변경 시나리오', description: 'SCN01에서 Job 2와 Job 1의 순서를 변경'});
|
||||
|
||||
// 2. SCN01에 포함된 Job들을 찾아 SCN04에 :INCLUDES 관계로 연결합니다. (수정된 부분)
|
||||
// WITH 절을 사용하여 s4를 명시적으로 전달합니다.
|
||||
WITH s4
|
||||
MATCH (s1:Scenario {id: 'SCN01'})-[:INCLUDES]->(j:Job)
|
||||
CREATE (s4)-[:INCLUDES]->(j);
|
||||
|
||||
// 3. SCN01의 순서를 기반으로 SCN04의 초기 순서를 복제합니다.
|
||||
// - STARTS_WITH 관계 복제
|
||||
WITH s4
|
||||
MATCH (s1:Scenario {id: 'SCN01'})-[sw:STARTS_WITH]->(start_job:Job)
|
||||
CREATE (s4)-[:STARTS_WITH]->(start_job);
|
||||
|
||||
// - NEXT 관계망 복제 (SCN04 시나리오에 종속된 NEXT 관계 생성)
|
||||
MATCH (s1:Scenario {id: 'SCN01'})-[:STARTS_WITH]->(start_job:Job)
|
||||
MATCH path = (start_job)-[:NEXT*]->(end_job:Job)
|
||||
WHERE NOT (end_job)-[:NEXT]->()
|
||||
WITH nodes(path) AS jobs
|
||||
UNWIND range(0, size(jobs)-2) AS i
|
||||
WITH jobs[i] AS from_job, jobs[i+1] AS to_job
|
||||
MATCH (s4:Scenario {id: 'SCN04'})
|
||||
MERGE (j1:Job {id: from_job.id})
|
||||
MERGE (j2:Job {id: to_job.id})
|
||||
CREATE (j1)-[:NEXT {scenario: 'SCN04'}]->(j2);
|
||||
|
||||
|
||||
// 4. SCN04에서 Job 1과 Job 2의 순서를 변경합니다. (기존 1->2->3 ... 을 2->1->3 ... 으로)
|
||||
// - 기존 관계 삭제
|
||||
MATCH (s4:Scenario {id: 'SCN04'})-[sw:STARTS_WITH]->(j1:Job {id: '1'})
|
||||
DELETE sw;
|
||||
|
||||
MATCH (j1:Job {id: '1'})-[n1:NEXT {scenario: 'SCN04'}]->(j2:Job {id: '2'})
|
||||
DELETE n1;
|
||||
|
||||
MATCH (j2:Job {id: '2'})-[n2:NEXT {scenario: 'SCN04'}]->(j3:Job {id: '3'})
|
||||
DELETE n2;
|
||||
|
||||
// - 새로운 관계 생성
|
||||
MATCH (s4:Scenario {id: 'SCN04'}), (j1:Job {id: '1'}), (j2:Job {id: '2'}), (j3:Job {id: '3'})
|
||||
CREATE (s4)-[:STARTS_WITH]->(j2),
|
||||
(j2)-[:NEXT {scenario: 'SCN04'}]->(j1),
|
||||
(j1)-[:NEXT {scenario: 'SCN04'}]->(j3);
|
||||
|
||||
RETURN "SCN04가 성공적으로 재생성되었습니다.";
|
||||
11
cypher_scripts/simulate_event_delay.cypher
Normal file
11
cypher_scripts/simulate_event_delay.cypher
Normal file
@@ -0,0 +1,11 @@
|
||||
// Event Simulation Query: Job Delay
|
||||
// Simulates an event where a specific job's duration increases.
|
||||
|
||||
// Match the specific Job instance (e.g., 'TBM 준비' with id 11)
|
||||
MATCH (j:Job {id: 11})
|
||||
|
||||
// Use SET to update its duration property
|
||||
SET j.duration = 50
|
||||
|
||||
// Return the updated job to confirm the change
|
||||
RETURN j.name, j.duration;
|
||||
12
cypher_scripts/visualize_scenario_SCN04.cypher
Normal file
12
cypher_scripts/visualize_scenario_SCN04.cypher
Normal file
@@ -0,0 +1,12 @@
|
||||
// SCN04 시나리오의 전체 구조를 시각화하는 쿼리
|
||||
// 시나리오 노드, 포함된 모든 Job, 그리고 작업 실행 순서(STARTS_WITH, NEXT)를 함께 조회합니다.
|
||||
|
||||
// p1 경로는 SCN04에 포함된(:INCLUDES) 모든 Job을 찾습니다.
|
||||
MATCH p1 = (s:Scenario {id: 'SCN04'})-[:INCLUDES]->(job:Job)
|
||||
|
||||
// p2 경로는 SCN04의 시작(:STARTS_WITH)부터 NEXT 관계로 이어진 작업 순서 전체를 찾습니다.
|
||||
// 이 경로는 SCN04에만 해당하는 NEXT 관계({scenario: 'SCN04'})를 따라갑니다.
|
||||
MATCH p2 = (s)-[:STARTS_WITH]->(start_job:Job)-[:NEXT* {scenario: 'SCN04'}]->(end_job:Job)
|
||||
|
||||
// 두 경로(p1, p2)를 모두 반환하여 시나리오의 전체 구조를 시각화합니다.
|
||||
RETURN p1, p2;
|
||||
Reference in New Issue
Block a user