# CouchDB Query Examples

This document demonstrates how the CouchDB design handles common query patterns for the Adopt-a-Street application.

## 1. User Authentication

### MongoDB Query
```javascript
const user = await User.findOne({ email: "john@example.com" });
```

### CouchDB Equivalent
```javascript
// Using Mango query
const user = await couchdbService.findUserByEmail("john@example.com");

// Raw Mango query
{
  "selector": {
    "type": "user",
    "email": "john@example.com"
  },
  "limit": 1
}
```

**Performance**: Single document lookup with indexed email field.

## 2. Geospatial Street Search

### MongoDB Query
```javascript
const streets = await Street.find({
  location: {
    $geoWithin: {
      $box: [[-74.1, 40.6], [-73.9, 40.8]]
    }
  },
  status: "available"
});
```

### CouchDB Equivalent
```javascript
// Using service method
const streets = await couchdbService.findStreetsByLocation([[-74.1, 40.6], [-73.9, 40.8]]);

// Raw Mango query
{
  "selector": {
    "type": "street",
    "status": "available",
    "location": {
      "$geoWithin": {
        "$box": [[-74.1, 40.6], [-73.9, 40.8]]
      }
    }
  }
}
```

**Performance**: Geospatial index on location field, filtered by status.

## 3. User's Activity Feed

### MongoDB Query (Multiple Queries)
```javascript
const posts = await Post.find({ user: userId }).sort({ createdAt: -1 });
const tasks = await Task.find({ completedBy: userId }).sort({ updatedAt: -1 });
const events = await Event.find({ participants: userId }).sort({ date: -1 });

// Combine and sort results
const activity = [...posts, ...tasks, ...events].sort((a, b) => b.createdAt - a.createdAt);
```

### CouchDB Equivalent (Single Query)
```javascript
// Using service method
const activity = await couchdbService.getUserActivity(userId, 50);

// Raw Mango query
{
  "selector": {
    "$or": [
      {
        "type": "post",
        "user.userId": "user_1234567890abcdef"
      },
      {
        "type": "task",
        "completedBy.userId": "user_1234567890abcdef"
      },
      {
        "type": "event",
        "participants": {
          "$elemMatch": {
            "userId": "user_1234567890abcdef"
          }
        }
      }
    ]
  },
  "sort": [{"createdAt": "desc"}],
  "limit": 50
}
```

**Performance**: Single query with compound OR selector, sorted by creation date.

## 4. Social Feed with User Data

### MongoDB Query (Population Required)
```javascript
const posts = await Post.find({})
  .populate('user', 'name profilePicture')
  .sort({ createdAt: -1 })
  .limit(20);

// For comments, separate query needed
const comments = await Comment.find({ post: { $in: posts.map(p => p._id) } })
  .populate('user', 'name profilePicture')
  .sort({ createdAt: 1 });
```

### CouchDB Equivalent (No Population Needed)
```javascript
// Get posts with embedded user data
const posts = await couchdbService.getSocialFeed(20);

// Get comments for posts
const postIds = posts.map(p => p._id);
const comments = await couchdbService.getPostComments(postIds[0]); // Example for one post

// Raw Mango query for posts
{
  "selector": {
    "type": "post"
  },
  "sort": [{"createdAt": "desc"}],
  "limit": 20
}

// Raw Mango query for comments
{
  "selector": {
    "type": "comment",
    "post.postId": {"$in": ["post_123", "post_456"]}
  },
  "sort": [{"createdAt": "asc"}]
}
```

**Performance**: User data embedded in posts, no additional lookups needed.

## 5. Leaderboard

### MongoDB Query
```javascript
const users = await User.find({ points: { $gt: 0 } })
  .select('name points profilePicture')
  .sort({ points: -1 })
  .limit(10);
```

### CouchDB Equivalent
```javascript
// Using service method
const leaderboard = await couchdbService.getLeaderboard(10);

// Raw Mango query
{
  "selector": {
    "type": "user",
    "points": {"$gt": 0}
  },
  "sort": [{"points": "desc"}],
  "limit": 10,
  "fields": ["_id", "name", "points", "profilePicture", "stats"]
}
```

**Performance**: Indexed query on points field with descending sort.

## 6. Street Details with Related Data

### MongoDB Query (Multiple Queries)
```javascript
const street = await Street.findById(streetId).populate('adoptedBy', 'name profilePicture');
const tasks = await Task.find({ street: streetId });
const reports = await Report.find({ street: streetId });

// Calculate stats manually
const stats = {
  tasksCount: tasks.length,
  completedTasksCount: tasks.filter(t => t.status === 'completed').length,
  reportsCount: reports.length,
  openReportsCount: reports.filter(r => r.status === 'open').length
};
```

### CouchDB Equivalent (Single Document)
```javascript
// Single document contains all needed data
const street = await couchdbService.getById(streetId);

// Raw Mango query
{
  "selector": {
    "_id": "street_abc123def456"
  }
}

// Result includes embedded stats:
{
  "_id": "street_abc123def456",
  "type": "street",
  "name": "Main Street",
  "adoptedBy": {
    "userId": "user_123",
    "name": "John Doe",
    "profilePicture": "https://cloudinary.com/image.jpg"
  },
  "stats": {
    "tasksCount": 5,
    "completedTasksCount": 3,
    "reportsCount": 2,
    "openReportsCount": 1
  }
}
```

**Performance**: Single document lookup with pre-calculated stats.

## 7. Event Management

### MongoDB Query
```javascript
const events = await Event.find({
  date: { $gte: new Date() },
  status: "upcoming"
}).populate('participants', 'name profilePicture');
```

### CouchDB Equivalent
```javascript
// Using service method
const events = await couchdbService.findByType('event', {
  date: { $gte: new Date().toISOString() },
  status: 'upcoming'
});

// Raw Mango query
{
  "selector": {
    "type": "event",
    "date": {"$gte": "2024-01-15T00:00:00Z"},
    "status": "upcoming"
  },
  "sort": [{"date": "asc"}]
}

// Result includes embedded participant data:
{
  "_id": "event_123",
  "type": "event",
  "title": "Community Cleanup",
  "participants": [
    {
      "userId": "user_123",
      "name": "John Doe",
      "profilePicture": "https://cloudinary.com/image.jpg",
      "joinedAt": "2024-01-10T10:00:00Z"
    }
  ],
  "participantsCount": 1
}
```

**Performance**: Participant data embedded, no population needed.

## 8. Badge System

### MongoDB Query (Complex Join)
```javascript
const user = await User.findById(userId).populate({
  path: 'earnedBadges',
  populate: {
    path: 'badge',
    model: 'Badge'
  }
});
```

### CouchDB Equivalent (Embedded Data)
```javascript
// Single user document contains badge data
const user = await couchdbService.findUserById(userId);

// Raw Mango query
{
  "selector": {
    "_id": "user_1234567890abcdef"
  }
}

// Result includes embedded badges:
{
  "_id": "user_1234567890abcdef",
  "type": "user",
  "name": "John Doe",
  "earnedBadges": [
    {
      "badgeId": "badge_123",
      "name": "Street Hero",
      "description": "Adopted 5 streets",
      "icon": "🏆",
      "rarity": "rare",
      "earnedAt": "2024-01-15T10:30:00Z",
      "progress": 100
    }
  ],
  "stats": {
    "badgesEarned": 1
  }
}
```

**Performance**: Badge data embedded in user document, no joins required.

## 9. Point Transaction History

### MongoDB Query
```javascript
const transactions = await PointTransaction.find({ user: userId })
  .sort({ createdAt: -1 })
  .limit(50);
```

### CouchDB Equivalent
```javascript
// Using service method
const transactions = await couchdbService.find({
  type: 'point_transaction',
  'user.userId': userId
}, {
  sort: [{ createdAt: 'desc' }],
  limit: 50
});

// Raw Mango query
{
  "selector": {
    "type": "point_transaction",
    "user.userId": "user_1234567890abcdef"
  },
  "sort": [{"createdAt": "desc"}],
  "limit": 50
}

// Result includes embedded user data:
{
  "_id": "transaction_123",
  "type": "point_transaction",
  "user": {
    "userId": "user_123",
    "name": "John Doe"
  },
  "amount": 10,
  "type": "task_completion",
  "description": "Completed task: Clean up litter",
  "relatedEntity": {
    "entityType": "Task",
    "entityId": "task_456",
    "entityName": "Clean up litter"
  },
  "balanceAfter": 150
}
```

**Performance**: Indexed query on user and creation date.

## 10. Real-time Updates with Changes Feed

### MongoDB (Change Streams)
```javascript
const changeStream = User.watch();
changeStream.on('change', (change) => {
  // Handle user changes
});
```

### CouchDB (Changes Feed)
```javascript
// Listen to changes feed
const changes = couchdbService.db.changes({
  since: 'now',
  live: true,
  include_docs: true
});

changes.on('change', (change) => {
  const doc = change.doc;
  
  // Handle different document types
  switch (doc.type) {
    case 'user':
      // Handle user updates
      break;
    case 'post':
      // Handle new posts
      break;
    case 'event':
      // Handle event updates
      break;
  }
});

// Filter by document type
const userChanges = couchdbService.db.changes({
  since: 'now',
  live: true,
  include_docs: true,
  filter: '_design/app',
  selector: {
    type: 'user'
  }
});
```

**Performance**: Native real-time updates with filtering capabilities.

## Performance Comparison Summary

| Query Pattern | MongoDB | CouchDB | Performance Impact |
|---------------|---------|---------|-------------------|
| User Auth | 1 query + index | 1 query + index | Similar |
| Social Feed | 1 query + populate | 1 query (embedded) | CouchDB faster |
| User Activity | 3 queries + combine | 1 query (OR) | CouchDB faster |
| Leaderboard | 1 query + index | 1 query + index | Similar |
| Street Details | 4 queries + calc | 1 query (embedded) | CouchDB much faster |
| Event Management | 1 query + populate | 1 query (embedded) | CouchDB faster |
| Badge System | Complex populate | Embedded data | CouchDB much faster |
| Real-time Updates | Change Streams | Changes Feed | CouchDB more flexible |

## Key Benefits of CouchDB Design

1. **Reduced Query Complexity**: Most common queries become single-document lookups
2. **Better Read Performance**: Embedded data eliminates JOIN operations
3. **Simplified Application Logic**: No need for complex population strategies
4. **Improved Offline Support**: Rich documents enable better offline functionality
5. **Real-time Capabilities**: Native changes feed with flexible filtering
6. **Scalability**: Denormalized design scales well with read-heavy workloads

## Trade-offs and Mitigations

1. **Data Duplication**: User data appears in multiple documents
   - **Mitigation**: Use changes feed to propagate updates
   
2. **Update Complexity**: Changes require updating multiple documents
   - **Mitigation**: Batch updates and background reconciliation jobs
   
3. **Storage Overhead**: Larger documents due to embedded data
   - **Mitigation**: Selective embedding based on access patterns
   
4. **Consistency**: Eventual consistency for related data
   - **Mitigation**: Application-level consistency checks and reconciliation

This CouchDB design prioritizes read performance and user experience, which aligns perfectly with the social community nature of the Adopt-a-Street application where most operations are reads rather than writes.