TerminusDB Schemas
Reference for the TerminusDB schema used in PBS Knowledge.
Schema Overview
The schema is defined in backend/src/schema/pbs-schema.json and defines all entity types, their properties, and relationships.
Schema Structure
{
"@context": {
"@base": "terminusdb:///data/",
"@schema": "terminusdb:///schema#",
"xsd": "http://www.w3.org/2001/XMLSchema#"
},
"@graph": [
// Class definitions
// Enum definitions
]
}
Core Entity Types
Person (Abstract)
Base class for all people:
{
"@id": "@schema:Person",
"@type": "Class",
"@abstract": [],
"first_name": "xsd:string",
"last_name": "xsd:string",
"email": { "@type": "Optional", "@class": "xsd:string" },
"dartmouth_id": { "@type": "Optional", "@class": "xsd:string" },
"bio": { "@type": "Optional", "@class": "xsd:string" },
"education": { "@type": "Set", "@class": "xsd:string" }
}
Faculty
Extends Person:
{
"@id": "@schema:Faculty",
"@type": "Class",
"@inherits": ["@schema:Person"],
"title": { "@type": "Optional", "@class": "xsd:string" },
"appointment_type": { "@type": "Optional", "@class": "@schema:AppointmentType" },
"research_interests": { "@type": "Set", "@class": "xsd:string" },
"openalex_id": { "@type": "Optional", "@class": "xsd:string" },
"orcid": { "@type": "Optional", "@class": "xsd:string" }
}
UndergraduateStudent
{
"@id": "@schema:UndergraduateStudent",
"@type": "Class",
"@inherits": ["@schema:Person"],
"class_year": { "@type": "Optional", "@class": "xsd:integer" },
"declared_majors": { "@type": "Set", "@class": "@schema:Degree" },
"declared_minors": { "@type": "Set", "@class": "@schema:Degree" },
"advisors": { "@type": "Set", "@class": "@schema:Faculty" }
}
GraduateStudent
{
"@id": "@schema:GraduateStudent",
"@type": "Class",
"@inherits": ["@schema:Person"],
"program": { "@type": "Optional", "@class": "@schema:AcademicProgram" },
"year_in_program": { "@type": "Optional", "@class": "xsd:integer" },
"advisors": { "@type": "Set", "@class": "@schema:Faculty" },
"committee": { "@type": "Set", "@class": "@schema:Faculty" }
}
Academic Entities
Course
{
"@id": "@schema:Course",
"@type": "Class",
"course_code": "xsd:string",
"title": "xsd:string",
"description": { "@type": "Optional", "@class": "xsd:string" },
"credits": { "@type": "Optional", "@class": "xsd:decimal" },
"prerequisites": { "@type": "Set", "@class": "@schema:Course" }
}
Section
{
"@id": "@schema:Section",
"@type": "Class",
"course": "@schema:Course",
"term": "xsd:string",
"section_number": "xsd:string",
"instructors": { "@type": "Set", "@class": "@schema:Faculty" },
"enrollment_cap": { "@type": "Optional", "@class": "xsd:integer" }
}
Degree
{
"@id": "@schema:Degree",
"@type": "Class",
"name": "xsd:string",
"degree_type": "@schema:DegreeType",
"description": { "@type": "Optional", "@class": "xsd:string" },
"total_credits": { "@type": "Optional", "@class": "xsd:integer" }
}
Research Entities
Lab
{
"@id": "@schema:Lab",
"@type": "Class",
"name": "xsd:string",
"description": { "@type": "Optional", "@class": "xsd:string" },
"pi": "@schema:Faculty",
"members": { "@type": "Set", "@class": "@schema:Person" },
"website": { "@type": "Optional", "@class": "xsd:string" }
}
Publication
{
"@id": "@schema:Publication",
"@type": "Class",
"title": "xsd:string",
"authors": { "@type": "List", "@class": "xsd:string" },
"venue": { "@type": "Optional", "@class": "xsd:string" },
"year": { "@type": "Optional", "@class": "xsd:integer" },
"doi": { "@type": "Optional", "@class": "xsd:string" },
"citation_count": { "@type": "Optional", "@class": "xsd:integer" },
"pbs_authors": { "@type": "Set", "@class": "@schema:Person" }
}
Enum Types
Defining Enums
{
"@id": "@schema:DegreeType",
"@type": "Enum",
"@value": ["BS", "BA", "Minor", "PhD", "MA", "Certificate"]
}
Important Enums
| Enum | Values |
|---|---|
DegreeType | BS, BA, Minor, PhD, MA |
AppointmentType | tenure_track, research, adjunct |
MilestoneStatus | not_started, in_progress, submitted, approved |
ApprovalRole | advisor, committee_member, department_admin |
caution
Always use @value (singular) for enum definitions, not @values (plural).
Property Types
Required vs Optional
// Required
"name": "xsd:string"
// Optional
"bio": { "@type": "Optional", "@class": "xsd:string" }
Collections
// Set (unordered, unique)
"members": { "@type": "Set", "@class": "@schema:Person" }
// List (ordered, allows duplicates)
"authors": { "@type": "List", "@class": "xsd:string" }
// Array (ordered, allows duplicates)
"tags": { "@type": "Array", "@class": "xsd:string" }
References
// Single reference
"advisor": "@schema:Faculty"
// Multiple references
"advisors": { "@type": "Set", "@class": "@schema:Faculty" }
Schema Modifications
Adding a New Type
- Define the class in
pbs-schema.json - Add to
@grapharray - Load schema to database
- Update TypeScript types
- Create service and routes
Adding Properties
- Add property to class definition
- Choose appropriate type
- Set required or optional
- Reload schema
- Update types and forms
Enum Values
Adding enum values:
{
"@id": "@schema:NewEnum",
"@type": "Enum",
"@value": ["value1", "value2", "value3"]
}
Loading Schema
Via Script
docker compose -f docker-compose.hybrid.yml exec backend \
node scripts/schema/load-schema.js
Via API
curl -X POST \
-u admin:password \
-H "Content-Type: application/json" \
"http://localhost:6363/api/document/admin/pbs_knowledge?graph_type=schema" \
-d @schema-types.json
Best Practices
Naming Conventions
- Class names: PascalCase (
UndergraduateStudent) - Property names: snake_case (
first_name) - Enum values: snake_case (
tenure_track)
Documentation
Add documentation to classes:
{
"@id": "@schema:Faculty",
"@type": "Class",
"@documentation": {
"@comment": "Faculty members at Dartmouth PBS",
"@label": "Faculty"
}
}
Schema Evolution
- Add new properties as Optional initially
- Never remove properties with existing data
- Use migrations for data transformations
- Test schema changes in development first