# Search Integration Design: Location Features

## 1. Search Index Integration

### Schema Modifications
```python
from django.contrib.postgres.indexes import GinIndex
from django.contrib.postgres.search import SearchVectorField

class SearchIndex(models.Model):
    # Existing fields
    content = SearchVectorField()
    
    # New location fields
    location_point = gis_models.PointField(srid=4326, null=True)
    location_geohash = models.CharField(max_length=12, null=True, db_index=True)
    location_metadata = models.JSONField(
        default=dict,
        help_text="Address, city, state for text search"
    )
    
    class Meta:
        indexes = [
            GinIndex(fields=['content']),
            models.Index(fields=['location_geohash']),
        ]
```

### Indexing Strategy
1. **Spatial Indexing**:
   - Use PostGIS GiST index on `location_point`
   - Add Geohash index for fast proximity searches
   
2. **Text Integration**:
   ```python
   SearchIndex.objects.update(
       content=SearchVector('content') + 
       SearchVector('location_metadata__city', weight='B') +
       SearchVector('location_metadata__state', weight='C')
   )
   ```

3. **Update Triggers**:
   - Signal handlers on ParkLocation/RideLocation changes
   - Daily reindexing task for data consistency

## 2. "Near Me" Functionality

### Query Architecture
```mermaid
sequenceDiagram
    participant User
    participant Frontend
    participant Geocoder
    participant SearchService
    
    User->>Frontend: Clicks "Near Me"
    Frontend->>Browser: Get geolocation
    Browser->>Frontend: Coordinates (lat, lng)
    Frontend->>Geocoder: Reverse geocode
    Geocoder->>Frontend: Location context
    Frontend->>SearchService: { query, location, radius }
    SearchService->>Database: Spatial search
    Database->>SearchService: Ranked results
    SearchService->>Frontend: Results with distances
```

### Ranking Algorithm
```python
def proximity_score(point, user_point, max_distance=100000):
    """Calculate proximity score (0-1)"""
    distance = point.distance(user_point) 
    return max(0, 1 - (distance / max_distance))

def combined_relevance(text_score, proximity_score, weights=[0.7, 0.3]):
    return (text_score * weights[0]) + (proximity_score * weights[1])
```

### Geocoding Integration
- Use Nominatim for address → coordinate conversion
- Cache results for 30 days
- Fallback to IP-based location estimation

## 3. Search Filters

### Filter Types
| Filter | Parameters | Example |
|--------|------------|---------|
| `radius` | `lat, lng, km` | `?radius=40.123,-75.456,50` |
| `bounds` | `sw_lat,sw_lng,ne_lat,ne_lng` | `?bounds=39.8,-77.0,40.2,-75.0` |
| `region` | `state/country` | `?region=Ohio` |
| `highway` | `exit_number` | `?highway=Exit 42` |

### Implementation
```python
class LocationFilter(SearchFilter):
    def apply(self, queryset, request):
        if 'radius' in request.GET:
            point, radius = parse_radius(request.GET['radius'])
            queryset = queryset.filter(
                location_point__dwithin=(point, Distance(km=radius))
        
        if 'bounds' in request.GET:
            polygon = parse_bounding_box(request.GET['bounds'])
            queryset = queryset.filter(location_point__within=polygon)
        
        return queryset
```

## 4. Performance Optimization

### Strategies
1. **Hybrid Indexing**:
   - GiST index for spatial queries
   - Geohash for quick distance approximations
   
2. **Query Optimization**:
   ```sql
   EXPLAIN ANALYZE SELECT * FROM search_index 
   WHERE ST_DWithin(location_point, ST_MakePoint(-75.456,40.123), 0.1);
   ```

3. **Caching Layers**:
   ```mermaid
   graph LR
   A[Request] --> B{Geohash Tile?}
   B -->|Yes| C[Redis Cache]
   B -->|No| D[Database Query]
   D --> E[Cache Results]
   E --> F[Response]
   C --> F
   ```

4. **Rate Limiting**:
   - 10 location searches/minute per user
   - Tiered limits for authenticated users

## 5. Frontend Integration

### UI Components
1. **Location Autocomplete**:
   ```javascript
   <LocationSearch 
     onSelect={(result) => setFilters({...filters, location: result})}
   />
   ```

2. **Proximity Toggle**:
   ```jsx
   <Toggle 
     label="Near Me"
     onChange={(enabled) => {
       if (enabled) navigator.geolocation.getCurrentPosition(...)
     }}
   />
   ```

3. **Result Distance Indicators**:
   ```jsx
   <SearchResult>
     <h3>{item.name}</h3>
     <DistanceBadge km={item.distance} />
   </SearchResult>
   ```

### Map Integration
```javascript
function updateMapResults(results) {
  results.forEach(item => {
    if (item.type === 'park') {
      createParkMarker(item);
    } else if (item.type === 'cluster') {
      createClusterMarker(item);
    }
  });
}
```

## Rollout Plan
1. **Phase 1**: Index integration (2 weeks)
2. **Phase 2**: Backend implementation (3 weeks)
3. **Phase 3**: Frontend components (2 weeks)
4. **Phase 4**: Beta testing (1 week)
5. **Phase 5**: Full rollout

## Metrics & Monitoring
- Query latency percentiles
- Cache hit rate
- Accuracy of location results
- Adoption rate of location filters