Skip to main content

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​

EnumValues
DegreeTypeBS, BA, Minor, PhD, MA
AppointmentTypetenure_track, research, adjunct
MilestoneStatusnot_started, in_progress, submitted, approved
ApprovalRoleadvisor, 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​

  1. Define the class in pbs-schema.json
  2. Add to @graph array
  3. Load schema to database
  4. Update TypeScript types
  5. Create service and routes

Adding Properties​

  1. Add property to class definition
  2. Choose appropriate type
  3. Set required or optional
  4. Reload schema
  5. 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