Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Warning

This has been moved to https://github.com/edx/edx-platform/blob/master/lms/djangoapps/grades/docs/data-model.rst and should be deprecated in favor of that copy.

Panel
borderColor#3572b0
bgColor#ebf2f9
titleColor#205081
borderWidth2
titleTable of Contents
Table of Contents

As explained in Robust Grades Design, there are several reasons to persist a learner's computed grade in the database. This document summarizes the persisted data models for learners' grades, at the course-level, subsection-level, and problem-level.

Course Grades

Table Name: grades_persistentcoursegrade

Table Description: Persistent values for learners' course grades.

Indices from Uniqueness Constraint: ('course_id', 'user_id')

  • course_id

  • course_id, user_id

Additional Indices:

  • user_id

  • course_id, passed_timestamp

Fields:

...

Field name

...

Type

...

Description

...

Include in Data Package

...

course_id

...

CourseKey

...

Course key of the containing course.

Example:
course-v1:org+course+run (for new-type courses) or
org/course/run (for old-type courses)

...

Y

...

user_id

...

Integer

...

User ID of the learner.

Example: 41446

...

Y

...

course_edited_timestamp

...

DateTime

Last edited timestamp of the course when the grade was computed.
Currently used for debugging purposes only. 

...

N

...

course_version

...

String (255)

...

The version number of the course in the Split Modulestore when the grade was computed.
Currently used for debugging purposes only. 

Note: The old Mongo modulestore doesn't support versions and so this field will be NULL for those courses. The "course_edited_timestamp" field should be used instead to understand dated information of the course content.

Example: 58ff632f00d9e7501e0148c4

...

N

...

grading_policy_hash

...

String (255)

...

A SHA-1 digest of the course grading policy.  It allows us to detect and update grades whenever the policy changes.

Example: NiGhcAFSrpyijXbow/XKE1Cp1GA=

...

Y**

...

percent_grade

...

Float

...

The learner's calculated course grade as a decimal percentage, per grading policy.

Example: 0.91 (means 91%)

...

Y

...

letter_grade

...

String (255)

...

The learner's calculated course grade as a letter value (e.g., A→D, Pass), per grading policy.  If the learner's grade is Fail or F, this cell value is empty.

Example: Pass or A

...

Y

...

passed_timestamp

...

DateTime

...

Time when the learner first passed the course.  If this cell value is empty, the learner never passed the course.  If this cell value is non-empty but the letter_grade value is empty, the learner transitioned from passing to not passing.

Note: There will be a lag in time from when the learner submitted the problem that caused them to pass and when the grade was computed (asynchronously by the platform post external grader, ORA grading, etc).

Example: 2017-05-02 15:51:04.395055

...

Y

...

created

...

DateTime

...

Time the course grade was first calculated for this user for this course.

Note: Backfilled grades will have this value set to the time the grade was eventually computed and backfilled.

...

Y

...

modified

...

DateTime

...

Time the course grade was last updated for this user for this course.

Note: Backfilled grades will have this value set to the time the grade was eventually computed and backfilled.

...

Y

** may require additional documentation/FAQ to be useful

Expected Read Use Cases:

...

Use case for reading from the table

...

Feature/team

...

Required Indices

(to be completed by engineering team)

...

Progress page displays learner's course grade, along with other grade breakdown info

...

LMS Progress Page

...

course_id, user_id

...

Course dashboard displays learner's course grade for each enrolled course

...

LMS Student Dashboard

...

user_id

...

Grade report generates CSV with course grade for each learner in the course

...

LMS Grade Report

...

course_id

...

Measure course completion statistics.

...

Analytics/Course Completion

...

course_id, passed_timestamp

Subsection Grades

There are two tables that work in conjunction for storing subsection grades: Subsection Grade and Visible Blocks.

There are also 2 tables that work together to override subsection grades: Subsection Grade Overrides and Subsection Grade Override History

Subsection Grade Table

Table Name: grades_persistentsubsectiongrade

Table Description: Persistent values for learners' subsection grades.

Indices from Uniqueness Constraint: ('course_id', 'user_id', 'usage_key')

  • course_id

  • course_id, user_id

  • course_id, user_id, usage_key

Additional Indices:

  • visible_blocks_hash

Fields:

...

Field name

...

Type

...

Description

...

Include in DP

...

course_id

...

CourseKey

...

Course key of the containing course.

Example:
course-v1:org+course+run (for new-type courses) or
org/course/run (for old-type courses)

...

Y

...

user_id

...

Integer

...

User ID of the learner.

Example: 41446

...

Y

...

usage_key

...

UsageKey

...

Usage key of the subsection. (This has other aliases: 'module_id', 'location')

Example:
block-v1:org+course+run+type@sequential+block@1234 (for new courses) or
i4x://org/course/sequential/1234 (for old-type courses)

...

Y

...

subtree_edited_timestamp

...

DateTime

...

Last edited timestamp of the content of the subsection or any of its descendants when the grade was computed.
Currently used for debugging purposes only.

Example: 2016-12-21 15:50:23.645000

...

N

...

course_version

...

String (255)

...

The version number of the course in the Split Modulestore when the grade was computed.
Currently used for debugging purposes only.

Example: 58ff632f00d9e7501e0148c4

...

N

...

visible_blocks

...

VisibleBlocks

...

Foreign key to the grades_visibleblocks table.

...

N

...

earned_all

...

Float

...

The user's aggregated "total_weighted_earned" score in the subsection, calculated by summing all "weighted_earned" values of all problems in the subsection.

...

Y

...

possible_all

...

Float

...

The aggregated "total_weighted_possible" score in the subsection, calculated by summing all "weighted_possible" values of all problems in the subsection.

...

Y

...

earned_graded

...

Float

...

The user's aggregated "total_weighted_earned" score in the subsection, calculated by summing all "weighted_earned" values of all graded problems in the subsection.

...

Y

...

possible_graded

...

Float

...

The aggregated "total_weighted_possible" score in the subsection, calculated by summing all "weighted_possible" values of all graded problems in the subsection.

...

Y

...

first_attempted

...

DateTime

...

Time of the user's first attempt at a problem in the subsection. If the user has not attempted a subsection, the entry for that subsection will be absent.

Note: Backfilled grades will use best-effort to derive a value for this - by computing a minimum of all the "created" dates on the attempted scores for the available problems in the subsection.

...

Y

...

created

...

DateTime

...

Time the subsection grade was first calculated for this user for this subsection.

Note: Backfilled grades will have this value set to the time the grade was eventually computed and backfilled.

...

Y

...

modified

...

DateTime

...

Time the subsection grade was last updated for this user for this subsection.

Note: Backfilled grades will have this value set to the time the grade was eventually computed and backfilled.

...

Y

Expected Read Use Cases:

...

Use case for reading from the table

...

Feature/team

...

Required Indices

(to be completed by engineering team)

...

Progress page displays learner's subsection grade breakdown

...

LMS Progress Page

...

course_id, user_id

...

Detailed grade report generates CSV with subsection grade for each learner in the course

...

LMS Grade Report

...

course_id

...

Compare with previous grade to see whether it should be conditionally updated

...

Rescore to Increase

...

course_id, user_id, usage_key

Visible Blocks Table

Table Name: grades_visibleblocks

Table Description: Stores an ordered list of visible blocks within a subsection for a learner at the time of computing the subsection grade.  It is expected that multiple learners will share access to the same list of visible blocks and hence this data is stored in a separate table so it can be referred to by multiple rows in the Subsection Grade table.

Indices from Uniqueness Constraint: ('hashed)

  • hashed

Additional Indices:

  • course_id

Fields:

...

Field name

...

Type

...

Description

...

Include in DP

...

course_id

...

CourseKey

...

Course key of the containing course.

...

N

...

hashed

...

String (100)

...

A SHA1 hash of the blocks_json value.

...

N

...

blocks_json

...

LongText

...

A JSON with the following information:

  • version: An integer representing the version number of the data format.

  • course_key: Serialized CourseKey of the containing course.

  • blocks: An ordered list of serialized UsageKeys of all blocks that are accessible to the user within a particular subsection.

Note: The blocks field contains a list of usage keys of all blocks within a subsection that are visible to the user at the time of computing the user's subsection grade.  The value changes whenever users' access to content within the subsection changes: cohort assignment change, role change, course team adds/removes unit/problem, etc. When changed, a new row is created in the table with a corresponding new hash value.

...

N

Subsection Grade Overrides

Table Name: grades_persistentsubsectiongradeoverride

Table Description: Stores the most recent override for a given subsection. In grade calculation, supersedes persisted subsection grade totals. The historical version of this table (grades_historicalpersistentsubsectiongradeoverride) captures a rolling list of previous overrides for audit purposes.

Indices from Uniqueness Constraint: (id)

  • id

Additional Indices:

  • created

  • modified

  • grade_id

Fields:

...

Field name

...

Type

...

Description

...

id

...

int(11)

...

Auto-incrementing ID of the override

...

created

...

datetime(6)

...

When the override was first created

...

modified

...

datetime(6)

...

When the override was last modified

...

earned_all_override

...

double

...

The total number of earned points (graded and ungraded) to be overridden.
Note: It’s unclear how this is actually used since this is null in some cases and wouldn’t factor into grade calculation.

...

possible_all_override

...

double

...

Total number of possible points (both graded and ungraded) for a subsection.

...

earned_graded_override

...

double

...

The points to be overridden for for the subsection.

...

possible_graded_override

...

double

...

The total possible graded score for the subsection.

...

grade_id

...

bigint(20) unsigned

...

1:1 mapping to a grades_persistentsubsectiongrade.id, specifying which grade this override applies to

...

override_reason

...

varchar(300)

...

Instructor provided reason for override

Example: Student bribed me with doughnuts so I’m increasing their score

...

system

...

varchar(100)

...

Where the override was performed.

Examples: GRADEBOOK, grade-import

Problem Scores

A learner's score for a specific problem is stored in either of 2 SQL tables, depending on the type of problem.

Courseware Student Module

Table Name: courseware_studentmodule

Table Description: A general-purpose storage for user-specific state for any xBlock/xModule (not just problem-types).  In addition to user-state, separate fields exist to store "earned" and "possible" grades for scorable blocks.

Indices from Uniqueness Constraint: ('student', 'module_id', 'course_id')

  • student

  • student, module_id

  • student, module_id, course_id

Additional Indices:

  • module_type

  • module_id

  • course_id

  • grade

  • done

  • created

  • modified

Fields:

...

Field name

...

Type

...

Description

...

module_type

...

String (32)

...

Block type of the xBlock in question.  For example: problem, video, html, chapter, etc.

...

module_id

...

UsageKey (255)

...

Usage key of the xBlock in question.

...

student

...

User

...

Foreign key to the User table.

...

course_id

...

CourseKey (255)

...

Course key of the containing course of the xBlock in question.

...

state

...

String

...

Free formed string that is contextually interpreted by the xBlock in question.

...

grade

...

Float

...

The user's "raw_earned" score on the problem.

...

max_grade

...

Float

...

The problem's "raw_possible" score at the time the user submitted the problem. Persisting this value here allows for the problem's content to change without affecting the user's score on the problem.

...

done

...

String

...

Possible values: Not Applicable, Finished, Incomplete

...

created

...

DateTime

...

Time the row was created.

...

modified

...

DateTime

...

Time the row was last modified.

ORA Submissions

Table Name: submissions_score

Table Description: One of the tables amongst the suite of tables used for ORA submissions.  This particular table stores the scores for ORA problems.

Indices from Uniqueness Constraint: ('id')

  • id

Additional Indices:

  • student_item_id

  • submission_id

  • created_at

Fields:

...

Field name

...

Type

...

Description

...

student_item

...

StudentItem

...

Foreign key to the submissions_studentitem table. A StudentItem represents a unique ORA / student / course combo.

...

submission

...

Submission

...

Foreign key to the submissions_submission table.

...

points_earned

...

Positive Integer

...

The user's "weighted_earned" score on the problem.

...

points_possible

...

Float

...

The problem's "weighted_possible" score at the time the user submitted the problem. Persisting this value here allows for the problem's content to change without affecting the user's score on the problem. 

Note, since points_earned and points_possible reflect the weighted values, the problem's weight is not applied for scores in the Submissions table when grades are aggregated.

...

reset

...

Boolean

...

Indicates that the score in this row should reset the current highest score.

...

created_at

...

DateTime

...

.