# Grateful Journal — Migration Guide

**Version:** 2.0 → 2.1 (Database Refactoring)  
**Date:** 2026-03-05

---

## Overview

This guide walks you through migrating your MongoDB database from the old schema (with duplicate users and string userId references) to the new refactored schema.

⚠️ **IMPORTANT:** Backup your database before starting. This process modifies your data.

---

## Pre-Migration Checklist

- [ ] No active users using the application
- [ ] Database backup created
- [ ] Python dependencies installed
- [ ] FastAPI backend stopped
- [ ] MongoDB running and accessible

---

## Step 1: Backup Your Database

**Critical:** Always backup before running migrations.

```bash
# Create timestamped backup
mongodump --db grateful_journal --out ./backup-$(date +%Y%m%d-%H%M%S)

# Verify backup
ls -lh backup-*/
```

This creates a directory like `backup-2026-03-05-120000` with all your data.

**Alternative: Cloud Backup (MongoDB Atlas)**

If using MongoDB Atlas, create a snapshot in the dashboard before proceeding.

---

## Step 2: Verify Current Database State

Before migration, inspect your current data:

```bash
# Check duplicate users by email
mongosh --db grateful_journal << 'EOF'
db.users.aggregate([
  { $group: { _id: "$email", count: { $sum: 1 }, ids: { $push: "$_id" } } },
  { $match: { count: { $gt: 1 } } }
])
EOF
```

**Expected Output:**  
If you see results, you have duplicates. The migration script will consolidate them.

---

## Step 3: Ensure Dependencies

The migration script uses PyMongo, which should already be installed:

```bash
cd /Users/jeet/Desktop/Jio/grateful-journal

# Check if pymongo is installed
python -c "import pymongo; print(pymongo.__version__)"

# If not installed:
pip install pymongo
```

---

## Step 4: Run the Migration Script

Navigate to the backend directory and run the migration:

```bash
cd /Users/jeet/Desktop/Jio/grateful-journal/backend

# Run the migration
python scripts/migrate_data.py
```

**Script Output:**

The script will:

1. Report duplicate users found
2. Map old duplicate user IDs to the canonical (oldest) user
3. Update all entries to reference the canonical user
4. Convert `userId` from string to ObjectId
5. Add `entryDate` field to entries
6. Add `encryption` metadata to entries
7. Verify data integrity

**Example Output:**

```
✓ Connected to MongoDB: grateful_journal

======================================================================
STEP 1: Deduplicating Users (keeping oldest)
======================================================================

📧 Email: jeet.debnath2004@gmail.com
   Found 12 duplicate users
   Keeping (earliest): ObjectId('69a7d6749a69142259e40394')
   Deleting (later):   ObjectId('69a7db0f8fbb489ac05ab945')
   Deleting (later):   ObjectId('69a7db178fbb489ac05ab946')
   ...

✓ Removed 11 duplicate users

======================================================================
STEP 2: Migrating Entries (userId string → ObjectId, add entryDate)
======================================================================

Total entries to process: 42

  ✓ Processed 100/150 entries
  ✓ Updated 150/150 entries

✓ Updated 150 entries

======================================================================
STEP 3: Verifying Data Integrity
======================================================================

Users collection: 1
Entries collection: 150

✓ All entries have valid user references

Sample entry structure:
  _id (entry): ObjectId('...') (ObjectId: True)
  userId: ObjectId('...') (ObjectId: True)
  entryDate present: True
  encryption present: True

======================================================================
✓ Migration Complete
======================================================================
Duplicate users removed: 11
Entries migrated: 150
Orphaned entries found: 0

✓ Data integrity verified successfully!
```

---

## Step 5: Create Indexes

After migration, create indexes for optimized performance:

```bash
python backend/scripts/create_indexes.py
```

**Expected Output:**

```
✓ Connected to MongoDB: grateful_journal

Creating indexes for 'users' collection...
  ✓ Created unique index on email
  ✓ Created index on createdAt

Creating indexes for 'entries' collection...
  ✓ Created compound index on (userId, createdAt)
  ✓ Created compound index on (userId, entryDate)
  ✓ Created index on tags
  ✓ Created index on entryDate

============================================================
✓ Index Creation Complete
============================================================
Total indexes created: 7
  • users.email_unique
  • users.createdAt_desc
  • entries.userId_createdAt
  • entries.userId_entryDate
  • entries.tags
  • entries.entryDate_desc

✓ Disconnected from MongoDB
```

---

## Step 6: Verify Schema

Verify the new schema is correct:

```bash
mongosh --db grateful_journal << 'EOF'
// Check user structure
db.users.findOne()

// Check entry structure
db.entries.findOne()

// Count documents
db.users.countDocuments({})
db.entries.countDocuments({})

// Verify indexes
db.users.getIndexes()
db.entries.getIndexes()
EOF
```

**Expected Sample Output:**

```javascript
// User document
{
  _id: ObjectId("507f1f77bcf86cd799439011"),
  email: "jeet.debnath2004@gmail.com",
  displayName: "Jeet Debnath",
  photoURL: "https://...",
  theme: "light",
  createdAt: ISODate("2026-03-04T06:51:32.598Z"),
  updatedAt: ISODate("2026-03-05T10:30:00.000Z")
}

// Entry document
{
  _id: ObjectId("507f1f77bcf86cd799439012"),
  userId: ObjectId("507f1f77bcf86cd799439011"),  // ← Now ObjectId!
  title: "Today's Gratitude",
  content: "I'm grateful for...",
  mood: "grateful",
  tags: ["family", "work"],
  isPublic: false,
  entryDate: ISODate("2026-03-05T00:00:00.000Z"),  // ← New field!
  createdAt: ISODate("2026-03-05T12:30:15.123Z"),
  updatedAt: ISODate("2026-03-05T12:30:15.123Z"),
  encryption: {                                      // ← New field!
    encrypted: false,
    iv: null,
    algorithm: null
  }
}
```

---

## Step 7: Test Backend

Start the backend and verify it works with the new schema:

```bash
cd /Users/jeet/Desktop/Jio/grateful-journal/backend

# Start the backend (in a new terminal)
python -m uvicorn main:app --reload --port 8001
```

**Test endpoints:**

```bash
# Health check
curl http://localhost:8001/health

# Get user by email (replace with your email)
curl -X GET "http://localhost:8001/api/users/by-email/jeet.debnath2004@gmail.com"

# Get user entries
curl -X GET "http://localhost:8001/api/entries/{user_id}?limit=10&skip=0"
```

Expected: All requests succeed with 200 status.

---

## Step 8: Restart Frontend

Once confident the backend works, restart the frontend:

```bash
# In a new terminal
cd /Users/jeet/Desktop/Jio/grateful-journal
npm run dev  # or your dev command
```

Test the full application:

- Login via Google
- Create an entry
- View entries in history
- Check calendar view

---

## Rollback Procedure

If something goes wrong:

```bash
# Restore from backup
mongorestore --drop --db grateful_journal ./backup-2026-03-05-120000

# Restart backend and frontend
```

This will revert the database to its pre-migration state.

---

## Troubleshooting

### Issue: "invalid ObjectId" errors

**Cause:** Some entries still have string userId references.  
**Fix:** Re-run the migration script:

```bash
python backend/scripts/migrate_data.py
```

### Issue: Entries not showing up

**Cause:** userId is still a string in old entries.  
**Fix:** Check the entry structure:

```bash
mongosh --db grateful_journal
db.entries.findOne()  # Check userId type
```

If userId is a string, run migration again.

### Issue: "duplicate key error" on email index

**Cause:** Index creation failed due to duplicate emails.  
**Fix:** The migration script handles this, but if you hit this:

```bash
# Rerun migration
python scripts/migrate_data.py
```

### Issue: Script won't run

```bash
# Ensure you're in the backend directory
cd /Users/jeet/Desktop/Jio/grateful-journal/backend

# Check Python path
python --version

# Run with explicit module path
python -m scripts.migrate_data
```

### Issue: MongoDB connection refused

```bash
# Check if MongoDB is running
mongosh

# If not running, start it:
# On macOS with Homebrew:
brew services start mongodb-community

# Or manually:
mongod
```

---

## Post-Migration

### Update Documentation

- [x] Update [SCHEMA.md](./SCHEMA.md) with new schema
- [x] Update [models.py](./models.py)
- [x] Update router docstrings

### Performance Tuning

Monitor slow queries:

```bash
mongosh --db grateful_journal << 'EOF'
// Monitor slow queries
db.setProfilingLevel(1, { slowms: 100 })

// Check profiling
db.system.profile.find().pretty()
EOF
```

### Data Analysis

Check migration statistics:

```bash
mongosh --db grateful_journal << 'EOF'
// Total users and entries
db.users.countDocuments({})
db.entries.countDocuments({})

// Entries with encryption
db.entries.countDocuments({ "encryption.encrypted": true })

// Entries without entryDate (should be 0)
db.entries.countDocuments({ entryDate: { $exists: false } })
EOF
```

---

## Next Steps

1. **Monitor**: Watch logs for any errors or warnings
2. **Test**: Thoroughly test all features (login, create, read, update, delete)
3. **Celebrate**: You've successfully migrated! 🎉

---

## Support

If you encounter issues:

1. Check [SCHEMA.md](./SCHEMA.md) for schema details
2. Review backend logs: `tail -f logs/backend.log`
3. Inspect MongoDB: Use mongosh to query directly
4. Consult the code: Check [routers/users.py](./routers/users.py) and [routers/entries.py](./routers/entries.py)

---

_Happy journaling! 📔_
