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