Problem
The API depends on 10 MongoDB views currently in Atlas. None of these views have their aggregation pipelines defined in the repository.
Current State Analysis
Views that exist in Atlas (10):
combined-meetings
scheduled-meetings
unscheduled-meetings
unique-languages-view
unique-languages-scheduled
unique-languages-unscheduled
unique-types-view
unique-types-scheduled
unique-types-unscheduled
group-view — Used by the /api/v1/meetings/:slug/related-group-info endpoint
These views exist only in MongoDB Atlas, defined via Compass on a local machine. There is no documented path to recreating them from source control.
Current Impact
- Single point of failure: View definitions live only in Atlas and on one local machine
- No disaster recovery path: If Atlas project is deleted or Compass definitions are lost, views cannot be recreated
- No onboarding path: New contributors cannot spin up a working dev environment without manual intervention
- No change tracking: Relationship between source schema and view contract must be rediscovered by reading application code
- README contains corrupted pipeline: The one pipeline example in README is for a name the code doesn't use and contains corrupted JSON (Slack URL embedded mid-pipeline)
At Risk
The API does not work without these views. If the view definitions are lost, the system must be reverse-engineered from application code to restore functionality.
Note: The events resource and events-view are excluded from this issue as that code will be removed in a future version.
Proposed Solution
Implement the script approach: create a migrate/views/ directory with executable migration scripts that recreate all views from scratch.
Implementation Steps
1. Export view definitions from MongoDB
Export all 10 views from Atlas
For each view, export the aggregation pipeline:
// In Compass or mongo shell - get full view definition including viewOn
db.getCollectionInfos({ name: "scheduled-meetings" })
// This returns an object like:
// {
// name: "scheduled-meetings",
// type: "view",
// options: {
// viewOn: "meeting", // ← This is the source collection
// pipeline: [ ... ] // ← This is what you need
// }
// }
For each of the 10 views, save both the viewOn value and the pipeline array. You'll need both for the migration script.
Save each pipeline as a JSON file in migrate/views/:
scheduled-meetings.json
unscheduled-meetings.json
combined-meetings.json
unique-languages-view.json
unique-languages-scheduled.json
unique-languages-unscheduled.json
unique-types-view.json
unique-types-scheduled.json
unique-types-unscheduled.json
group-view.json
2. Create migration script
Create migrate/views/create-views.ts (or .js) that:
- Connects to MongoDB using the same connection logic as the app
- Reads each JSON file from
migrate/views/
- Calls
db.createCollection(name, { viewOn: "source-collection", pipeline: [...] }) for each view
- Handles idempotency (drops existing view before creating, or checks if it exists)
- Provides clear success/failure feedback
Important: The viewOn parameter in the script must match the actual source collection/view for each:
- Base meeting views (
scheduled-meetings, unscheduled-meetings, combined-meetings) → viewOn: 'meeting'
- Language views (
unique-languages-*) → verify what these aggregate from (likely the meeting views)
- Type views (
unique-types-*) → verify what these aggregate from (likely the meeting views)
- Group view (
group-view) → viewOn: 'group'
You may need to inspect the exported pipelines to determine the correct viewOn values.
Example structure:
import { MongoClient } from 'mongodb'
import { readFileSync } from 'fs'
import { join } from 'path'
const VIEWS = [
{ name: 'scheduled-meetings', viewOn: 'meetings', file: 'scheduled-meetings.json' },
{ name: 'unscheduled-meetings', viewOn: 'meetings', file: 'unscheduled-meetings.json' },
{ name: 'combined-meetings', viewOn: 'meetings', file: 'combined-meetings.json' },
{ name: 'unique-languages-view', viewOn: 'meetings', file: 'unique-languages-view.json' },
{ name: 'unique-languages-scheduled', viewOn: 'scheduled-meetings', file: 'unique-languages-scheduled.json' },
{ name: 'unique-languages-unscheduled', viewOn: 'unscheduled-meetings', file: 'unique-languages-unscheduled.json' },
{ name: 'unique-types-view', viewOn: 'meetings', file: 'unique-types-view.json' },
{ name: 'unique-types-scheduled', viewOn: 'scheduled-meetings', file: 'unique-types-scheduled.json' },
{ name: 'unique-types-unscheduled', viewOn: 'unscheduled-meetings', file: 'unique-types-unscheduled.json' },
{ name: 'group-view', viewOn: 'group', file: 'group-view.json' },
]
async function createViews() {
const client = new MongoClient(process.env.MONGO_URI!)
await client.connect()
const db = client.db(process.env.MONGO_DB_NAME!)
for (const view of VIEWS) {
try {
// Drop existing view if it exists
await db.collection(view.name).drop().catch(() => {})
// Read pipeline from file
const pipeline = JSON.parse(
readFileSync(join(__dirname, view.file), 'utf-8')
)
// Create view
await db.createCollection(view.name, {
viewOn: view.viewOn,
pipeline
})
console.log(`✓ Created view: ${view.name}`)
} catch (err) {
console.error(`✗ Failed to create view ${view.name}:`, err)
throw err
}
}
await client.close()
}
createViews()
.then(() => console.log('\nAll views created successfully'))
.catch(err => {
console.error('\nView creation failed:', err)
process.exit(1)
})
3. Add npm script
In package.json:
{
"scripts": {
"migrate:views": "tsx migrate/views/create-views.ts"
}
}
4. Update documentation
In README.md:
- Add section "Database Setup" explaining how to run
npm run migrate:views
- Document required environment variables (
MONGO_URI, MONGO_DB_NAME)
- Note that the existing pipeline block is for reference only;
migrate/views/ is source of truth
- Add instructions for exporting views after making changes in Compass
Create migrate/views/README.md:
- Document what each view does and its source (
viewOn) collection/view
- List all 10 views with their purposes:
scheduled-meetings, unscheduled-meetings, combined-meetings - filtered views of meetings
unique-languages-*, unique-types-* - faceted aggregations for filters
group-view - group information lookup
- Explain the relationship between views and source collections
- Provide instructions for modifying and re-exporting views
- Document the migration script usage
5. Test the script
- Create a fresh Atlas database (or local MongoDB instance)
- Load source data (meetings, groups, events collections)
- Run
npm run migrate:views
- Verify all 12 views are created successfully
- Verify API works against the newly created views
- Test idempotency: run script again, should succeed without errors
Acceptance Criteria
Success Indicators
A new contributor with Atlas access can:
- Clone the repository
- Run
npm run migrate:views
- Have a working set of views against a fresh database
- Start the API successfully without manual view configuration
Tim's laptop is no longer the only place the view definitions live.
Notes
This is the single-keystone risk in the system. The API depends entirely on these views, and they exist nowhere in source control. If the Atlas project is deleted, if Compass definitions are lost, or if you step away from the project, there is no recovery path.
This is also the easiest risk to fix.
What This Does NOT Include
- Migrating to a different data store (the views work and are the right tool)
- Rewriting views as application code (views are appropriate for this use case)
- Versioning views as proper migrations (worth considering later, not now)
- Automated testing of view output (separate concern, can be added later)
Estimated Effort
4-5 hours including:
- Exporting all 10 view definitions
- Creating the migration script
- Testing against a fresh database
- Writing documentation
Problem
The API depends on 10 MongoDB views currently in Atlas. None of these views have their aggregation pipelines defined in the repository.
Current State Analysis
Views that exist in Atlas (10):
combined-meetingsscheduled-meetingsunscheduled-meetingsunique-languages-viewunique-languages-scheduledunique-languages-unscheduledunique-types-viewunique-types-scheduledunique-types-unscheduledgroup-view— Used by the/api/v1/meetings/:slug/related-group-infoendpointThese views exist only in MongoDB Atlas, defined via Compass on a local machine. There is no documented path to recreating them from source control.
Current Impact
At Risk
The API does not work without these views. If the view definitions are lost, the system must be reverse-engineered from application code to restore functionality.
Note: The
eventsresource andevents-vieware excluded from this issue as that code will be removed in a future version.Proposed Solution
Implement the script approach: create a
migrate/views/directory with executable migration scripts that recreate all views from scratch.Implementation Steps
1. Export view definitions from MongoDB
Export all 10 views from Atlas
For each view, export the aggregation pipeline:
For each of the 10 views, save both the
viewOnvalue and thepipelinearray. You'll need both for the migration script.Save each pipeline as a JSON file in
migrate/views/:scheduled-meetings.jsonunscheduled-meetings.jsoncombined-meetings.jsonunique-languages-view.jsonunique-languages-scheduled.jsonunique-languages-unscheduled.jsonunique-types-view.jsonunique-types-scheduled.jsonunique-types-unscheduled.jsongroup-view.json2. Create migration script
Create
migrate/views/create-views.ts(or.js) that:migrate/views/db.createCollection(name, { viewOn: "source-collection", pipeline: [...] })for each viewImportant: The
viewOnparameter in the script must match the actual source collection/view for each:scheduled-meetings,unscheduled-meetings,combined-meetings) →viewOn: 'meeting'unique-languages-*) → verify what these aggregate from (likely the meeting views)unique-types-*) → verify what these aggregate from (likely the meeting views)group-view) →viewOn: 'group'You may need to inspect the exported pipelines to determine the correct
viewOnvalues.Example structure:
3. Add npm script
In
package.json:{ "scripts": { "migrate:views": "tsx migrate/views/create-views.ts" } }4. Update documentation
In
README.md:npm run migrate:viewsMONGO_URI,MONGO_DB_NAME)migrate/views/is source of truthCreate
migrate/views/README.md:viewOn) collection/viewscheduled-meetings,unscheduled-meetings,combined-meetings- filtered views of meetingsunique-languages-*,unique-types-*- faceted aggregations for filtersgroup-view- group information lookup5. Test the script
npm run migrate:viewsAcceptance Criteria
migrate/views/npm run migrate:viewscommand documented and workingmigrate/views/README.mdcreated with view documentationSuccess Indicators
A new contributor with Atlas access can:
npm run migrate:viewsTim's laptop is no longer the only place the view definitions live.
Notes
This is the single-keystone risk in the system. The API depends entirely on these views, and they exist nowhere in source control. If the Atlas project is deleted, if Compass definitions are lost, or if you step away from the project, there is no recovery path.
This is also the easiest risk to fix.
What This Does NOT Include
Estimated Effort
4-5 hours including: