Learning Resource:
https://www.milowski.com/journal/entry/2024-06-26T12:00:00-07:00/
https://jtc1info.org/wp-content/uploads/2024/04/2024-Article-39075-Database-Language-GQL.docx.pdf
In GQL (Graph Query Language), the ISO standard syntax for comments is the same as in many other programming languages. You use two forward slashes (//) for single-line comments or /* and */ for multi-line comments.
EduSmartSchema declared via phrases:
https://shorten.wilenskid.pl/~d84zE
CREATE GRAPH TYPE EduSmartSchema AS {
NODE :Program {
program_id :: STRING NOT NULL, // PK
name :: STRING NOT NULL,
description :: STRING
},
NODE:Course {
course_id :: STRING NOT NULL, // PK
course_number :: STRING NOT NULL,
name :: STRING NOT NULL,
description :: STRING
},
NODE : Section {
section_number :: STRING NOT NULL, // PK
start_date :: DATE NOT NULL,
end_date :: DATE NOT NULL,
class_days_of_week :: STRING NOT NULL,
class_time :: STRING NOT NULL,
class_duration :: INTEGER NOT NULL,
lab_days_of_week:: STRING NOT NULL,
lab_time :: STRING NOT NULL,
lab_duration :: INTEGER NOT NULL
},
DIRECTED EDGE INCLUDES {} CONNECTING (Program -> Course),
DIRECTED EDGE SCHEDULED {} CONNECTING (Course -> Section),
DIRECTED EDGE PRE_REQUISITE {} CONNECTING (Course -> Course), //
NODE :Person {
person_id :: STRING NOT NULL, // PK
name :: STRING NOT NULL,
photo_url :: STRING,
givenName :: STRING,
familyName :: STRING NOT NULL,
birthDate :: DATE NOT NULL,
signupDate :: DATE NOT NULL
},
NODE :Student => :Person {
student_id :: STRING NOT NULL, // pk
roll_no :: STRING NOT NULL
} AS Student,
// create a separate Skill node
NODE Profile {
education_level :: STRING NOT NULL, // Background education level
work_experience :: STRING, // Details of work experience
english_reflections :: STRING, // Can be Summary or JSONString
iq_reflection :: STRING, // Can be Summary or JSONString
learning_style :: STRING, // Interests of the student i.e like cars so talk with car examples
current_level :: STRING, // Current knowledge level (beginner, intermediate, advanced)
last_updated :: DATE NOT NULL // Last profile update date
},
NODE Skill {
skill_id :: STRING NOT NULL, // Primary Key
name :: STRING NOT NULL, // Name of the skill (e.g., "Python", "Data Analysis")
description :: STRING, // Detailed description of the skill
category :: STRING, // Category or domain (e.g., "Programming", "Mathematics")
proficiency_level :: STRING, // Proficiency level (e.g., "Beginner", "Intermediate", "Advanced")
last_assessed :: DATE, // Date when the skill was last assessed or updated
access_source :: STRING, // Source of the skill data (e.g., "Quiz", "Assignment", "Self-Assessment")
reflections :: STRING // Generated by LLM based on AnswerSheet
},
DIRECTED EDGE HAS_SKILL {
proficiency :: STRING, // Student's proficiency level in the skill
date_acquired :: DATE // Date when the student acquired the skill
} CONNECTING (Profile -> Skill),
DIRECTED EDGE HAS_PROFILE {} CONNECTING (Student -> Profile),
DIRECTED EDGE TAKE_ADMISSION {} CONNECTING (Student -> Program),
DIRECTED EDGE REGISTERED {
fee_status:: STRING,
admission_date:: DATE
} CONNECTING (Student -> Section), // Suppose Fee Paid
NODE :Teacher => :Person {
teacher_id :: STRING NOT NULL // pk
} AS Teacher,
DIRECTED EDGE TEACHES {} CONNECTING (Teacher -> Section),
DIRECTED EDGE MANAGES_ASSESSMENT {} CONNECTING (Teacher -> Assessment),
DIRECTED EDGE MANAGES_TOPIC {} CONNECTING (Teacher -> Topic),
NODE :TextBook {
textbook_id :: STRING NOT NULL, // pk
title :: STRING NOT NULL,
author_name :: STRING NOT NULL,
description :: STRING
},
DIRECTED EDGE HAS_REQUIRED_TEXTBOOK {} CONNECTING (Course -> TextBook),
NODE :Topic {
topic_id :: STRING NOT NULL, // pk
title :: STRING NOT NULL,
url :: STRING,
details :: STRING,
topic_level :: INTEGER,
//maximum_level :: INTEGER,
last_reviewed :: DATE NOT NULL,
creation_date :: DATE NOT NULL,
sequence_number :: INT NOT NULL
},
DIRECTED EDGE COVERS {} CONNECTING (TextBook -> Topic),
DIRECTED EDGE CONTAINS_TOPIC CONNECTING (Topic -> Topic),
NODE :TopicContent {
id :: STRING NOT NULL, // pk
content :: STRING NOT NULL, // pk
embeddings :: ANY,
last_updated :: DATE NOT NULL
},
DIRECTED EDGE CONTAINS_CONTENT {} CONNECTING (Topic -> TopicContent),
DIRECTED EDGE COMPLETED_TOPIC
{
level :: INT NOT NULL,
assessment_date :: DATE
}
CONNECTING (Student -> Topic),
// QuestionBank Questions and Answers Related to Topics (CaseStudy is Skipped for Time)
NODE:Question {
question_id :: STRING NOT NULL, // pk
question_text :: STRING NOT NULL,
difficulty_level :: STRING,
points :: INT NOT NULL
},
NODE :FreeText => :Question {
reference_answer :: STRING NOT NULL
} AS FreeText,
NODE :CODING => :Question {
ideal_answer :: STRING NOT NULL
} AS CODING,
NODE :SingleSelect => :Question {
} AS SingleSelect,
NODE :MultiSelect => :Question {
} AS MultiSelect,
NODE :Option {
option_id :: STRING NOT NULL, // pk
answer_text :: STRING NOT NULL,
is_correct :: BOOLEAN NOT NULL
},
UNDIRECTED EDGE CONTAINS {} CONNECTING (Topic ~ Question),
DIRECTED EDGE HAS_SINGLE_OPTION {} CONNECTING (SingleSelect -> Option),
DIRECTED EDGE HAS_MULTIPLE_OPTION {} CONNECTING (MultiSelect -> Option),
DIRECTED EDGE IS_A_TYPE {} CONNECTING (Question -> SingleSelect),
DIRECTED EDGE IS_A_TYPE {} CONNECTING (Question -> MultiSelect),
DIRECTED EDGE IS_A_TYPE {} CONNECTING (Question -> Coding),
DIRECTED EDGE IS_A_TYPE {} CONNECTING (Question -> FreeText),
// Interaction Nodes and Student Assessment Tracking
// Use-Case:
// 1. End of Course (Assessment) 2. AfterTopic/s (Interaction) 3. OnBoarding
// 2. AfterTopic/s // (Interaction)
NODE :Interaction {
interaction_id :: STRING NOT NULL, // pk
total_questions :: INT, // number of questions
creation_date :: DATE NOT NULL,
end_date :: DATE
},
// StudentInteraction Node
NODE :StudentInteraction {
student_interaction_id :: STRING NOT NULL, // PK
status :: STRING NOT NULL, // 'assigned', 'in_progress', 'completed'
assigned_date :: DATE NOT NULL,
start_date :: DATE,
last_updated :: DATE,
percentage :: FLOAT,
score :: INT
},
// Learning Exchange Node for tracking Q&A
NODE :LearningExchange {
exchange_id :: STRING NOT NULL, // PK
student_response :: STRING NOT NULL, // The actual answer given
is_correct :: BOOLEAN, // Correctness flag
needs_reinforcement :: BOOLEAN, // Flag for further review
exchange_timestamp :: DATE NOT NULL,
sequence_number :: INTEGER NOT NULL, // Order in interaction
feedback :: STRING // Optional feedback/explanation
},
DIRECTED EDGE HAS_PARTICIPATION {} CONNECTING (Student -> StudentInteraction),
DIRECTED EDGE ASSIGNED_TO_INTERACTION {} CONNECTING (StudentInteraction -> Interaction),
DIRECTED EDGE COVERS_TOPIC {} CONNECTING (Interaction -> Topic),
DIRECTED EDGE INCLUDES_LEARNING_EXCHANGE {} CONNECTING (StudentInteraction -> LearningExchange),
DIRECTED EDGE ANSWERED_QUESTION {} CONNECTING (LearningExchange -> Question),
/* // 3. DEPRECIATED: InitialInteraction
NODE :InitialInteraction {
id :: STRING NOT NULL, // pk
title :: STRING NOT NULL,
total_questions :: INTEGER,
max_score :: INTEGER,
creation_date :: DATE NOT NULL,
questions::ANY,
max_duration_minutes:: INTEGER
},
// DIRECTED EDGE INITIATES {} CONNECTING (Student -> InitialInteraction),
// DIRECTED EDGE UPDATES {} CONNECTING (InitialInteraction -> Profile),
*/
// Interaction with IQ english & math will be same as above. Think of initalInteraction as quiz that is connected to questions.
DIRECTED EDGE REQUIRED_FOR {} CONNECTING (Quiz -> Course),
// 1. Assessment (This can be Quiz or Assessment)
// What will we have for Final Assessment ?
NODE : Assessment {
id :: STRING NOT NULL, // pk
title:: STRING ,
details :: STRING,
passing_score :: INTEGER
},
NODE :Assignment_Project {
id :: STRING NOT NULL, // pk
title :: STRING,
details :: STRING,
passing_score :: INTEGER,
max_duration :: INTEGER
},
DIRECTED EDGE INCLUDES_PROJECT {} CONNECTING (Assessment -> Assignment_Project),
DIRECTED EDGE HAS_QUIZ {} CONNECTING (Assessment -> Quiz),
DIRECTED EDGE MANDATORY_ASSESSMENT_FOR {due_date :: DATE NOT NULL} CONNECTING (Assessment -> Section),
DIRECTED EDGE ATTEMPTS_ASSESSMENT {
assessment_type :: STRING //midterm or final
} CONNECTING (Student -> Assessment),
//Edge to promote student in next course?
NODE :Quiz {
id :: STRING, // PK
title:: STRING ,
total_questions :: INTEGER,
max_score :: INTEGER,
time_duration :: INTEGER,
topics_count:: INTEGER
},
/* Right Now we don't have student attempted answers connected to Question. If this use case is required
We can create an Answers nodes connected AnswerSheet to Questions.
*/
NODE :AnswerSheet {
id :: STRING, // PK
question_ids :: LIST<ANY>, // Just Questions Metadata
// attempted_answers :: ANY, // store [{"question": "answer", "question_id": 1 }]
grade :: FLOAT,
start_time :: DATE,
end_time :: DATE
},
NODE :AttemptedAnswer {
id :: STRING, // PK
question :: STRING,
answer :: STRING,
score :: FLOAT
},
DIRECTED EDGE ASSIGNED_QUIZ {
assigned_date :: DATE NOT NULL,
due_date :: DATE NOT NULL
} CONNECTING (Student -> Quiz),
DIRECTED EDGE HAS_ATTEMPT {
attempt_date :: DATE NOT NULL,
submission_status :: STRING // ('draft', 'submitted', 'evaluated')
} CONNECTING (Student -> AnswerSheet),
DIRECTED EDGE CONTAINS_ATTEMPTED_ANSWER {} CONNECTING (AnswerSheet -> AttemptedAnswer),
DIRECTED EDGE IS_RESPONSE_TO_QUESTION {} CONNECTING (AttemptedAnswer -> Question),
DIRECTED EDGE HAS_RESPONSE {} CONNECTING (Quiz -> AnswerSheet),
DIRECTED EDGE BELONGS_TO {} CONNECTING (Quiz -> Course),
DIRECTED EDGE COVERS_TOPIC {} CONNECTING (Quiz -> TOPIC),
// Classes & Tracking
Node :OnlineSessionSchedule {
id :: STRING NOT NULL, // pk
zoom_link:: STRING,
topics_to_cover:: List<STRING>, // have topics to teach in 1 class
class_time :: DATE NOT NULL,
class_day :: STRING,
class_status:: BOOL
},
DIRECTED EDGE HAS_SECTION_SCHEDULE {} CONNECTING (Section -> OnlineSessionSchedule), //class attend
DIRECTED EDGE HAS_COURSE_SCHEDULE {} CONNECTING (Course -> OnlineSessionSchedule), //course has course schedule
DIRECTED EDGE TEACHES_TOPIC {"date":: STRING} CONNECTING (OnlineSessionSchedule -> Topic), //course has course schedule
Node :Notification {
id :: STRING NOT NULL, // pk
content:: STRING,
notification_time :: DATE NOT NULL
},
DIRECTED EDGE NOTIFIES_STUDENT {} CONNECTING (Notification -> Student),
DIRECTED EDGE MANAGES_NOTIFICATION {} CONNECTING (Teacher -> Notification),
DIRECTED EDGE NOTIFIES_SECTION {} CONNECTING (Notification -> Section),
DIRECTED EDGE NOTIFIES_COURSE {} CONNECTING (Notification -> Course)
/* Purpose of this node is to have a Quick Student Course Progress Overview. Think of it as a Short Term Memory for a Student in a Particular Course in context of AGENT as teacher.
// To be Updated after student Chatbot v1
Node :StudentCourseStatus {},
DIRECTED EDGE BELONGS_TO {} CONNECTING (StudentCourseStatus -> Course),
DIRECTED EDGE HAS_COURSE_MEMORY {} CONNECTING (Student -> StudentCourseStatus)*/
}
https://shorten.wilenskid.pl/fVVbWE
/* Insert nodes */
INSERT (:Program {name: 'Certified Generative AI Engineer', description: 'This is Agentic and Physical AI Program'})
INSERT (:Course {course_number: 'ai-101', name: 'Python AI', description: 'Coding Python using AI'})
MATCH (p : Program {name: 'Certified Generative AI Engineer'})
,(c : Course {course_number: 'ai-101'})
INSERT (p)-[:contains]->(c)
/* Insert two nodes and an edge */
INSERT (:Program {name: 'AI', description: 'AI Program' })
-[:contains {}]->
(:Course {course_number: 'ai-201', name: 'Generative AI', description: 'Coding in Generative AI'})