MongoDB uses collections instead of tables. References between documents use ObjectIds. The oauth token is embedded directly in the User document since it is a 1:1 relationship.
User
embeds -> oauthToken (access_token, scope, updated_at)
refs -> Repository (user: ObjectId)
refs -> Commit (repoId: ObjectId)
refs -> PullRequest (repoId: ObjectId)
refs -> Review (prId: ObjectId)
User
| Field | Type | Notes |
|---|---|---|
| _id | ObjectId | Auto-generated |
| githubId | Number (unique) | GitHub user ID |
| username | String | GitHub login |
| avatarUrl | String | |
| String | ||
| oauthToken.accessToken | String | Embedded subdocument |
| oauthToken.scope | String | |
| oauthToken.updatedAt | Date | |
| createdAt | Date | Mongoose timestamps |
Repository
| Field | Type | Notes |
|---|---|---|
| _id | ObjectId | |
| userId | ObjectId ref User | |
| githubRepoId | Number (unique) | |
| owner | String | GitHub org or user |
| name | String | Repo name |
| fullName | String | owner/name |
| private | Boolean | |
| syncedAt | Date | Last full sync |
Commit
| Field | Type | Notes |
|---|---|---|
| repoId | ObjectId ref Repository | |
| sha | String (unique) | |
| authorGithubId | Number | |
| message | String | |
| committedAt | Date | |
| additions | Number | |
| deletions | Number | |
| changedFiles | Number |
PullRequest
| Field | Type | Notes |
|---|---|---|
| repoId | ObjectId ref Repository | |
| githubPrId | Number (unique) | |
| number | Number | PR number in repo |
| title | String | |
| state | String | open/closed/merged |
| openedAt | Date | |
| closedAt | Date | |
| mergedAt | Date | |
| cycleTimeHours | Number | mergedAt - openedAt |
| additions | Number | |
| deletions | Number |
Review
| Field | Type | Notes |
|---|---|---|
| prId | ObjectId ref PullRequest | |
| reviewerGithubId | Number | |
| state | String | APPROVED/CHANGES_REQUESTED/COMMENTED |
| submittedAt | Date | |
| turnaroundHours | Number | submittedAt - pr.openedAt |
// Defined in Mongoose schemas
CommitSchema.index({ repoId: 1, committedAt: -1 });
PullRequestSchema.index({ repoId: 1, state: 1 });
PullRequestSchema.index({ mergedAt: -1 }, { sparse: true });
ReviewSchema.index({ prId: 1 });