A social knowledge tool for researchers built on ATProto
1# Collection Text Search Feature 2 3## Overview 4 5Enable text search over a user's collections so they can quickly find and select existing collections when adding cards. 6 7## Implementation Options 8 9Based on our CQRS and DDD architecture patterns, we have several strategic approaches: 10 11### Option 1: Extend Existing Query Use Case (Recommended) 12 13**Pattern**: Enhance `GetMyCollectionsUseCase` with search capability 14 15**Pros**: 16 17- Follows single responsibility - still "getting collections" 18- Reuses existing pagination, sorting, and enrichment logic 19- Maintains consistent API surface 20- Simpler client-side implementation 21 22**Implementation**: 23 24```typescript 25// Update existing query interface 26export interface GetMyCollectionsQuery { 27 curatorId: string; 28 page?: number; 29 limit?: number; 30 sortBy?: CollectionSortField; 31 sortOrder?: SortOrder; 32 searchText?: string; // NEW: Optional search parameter 33} 34 35// Update repository interface 36export interface ICollectionQueryRepository { 37 findByCreator( 38 curatorId: string, 39 options: CollectionQueryOptions & { searchText?: string }, // Enhanced options 40 ): Promise<PaginatedQueryResult<CollectionQueryResultDTO>>; 41} 42``` 43 44**Changes Required**: 45 46- Update `GetMyCollectionsQuery` interface 47- Update `ICollectionQueryRepository.findByCreator()` method signature 48- Update `DrizzleCollectionQueryRepository` implementation with text search logic 49- Update API client types and methods 50- Update HTTP controller to handle search parameter 51 52### Option 2: Dedicated Search Use Case 53 54**Pattern**: Create separate `SearchMyCollectionsUseCase` 55 56**Pros**: 57 58- Clear separation of concerns 59- Optimized specifically for search scenarios 60- Can implement different search algorithms/ranking 61- Easier to add search-specific features (highlighting, relevance scoring) 62 63**Implementation**: 64 65```typescript 66// New dedicated use case 67export interface SearchMyCollectionsQuery { 68 curatorId: string; 69 searchText: string; // Required for search 70 page?: number; 71 limit?: number; 72} 73 74export interface SearchMyCollectionsResult { 75 collections: CollectionSearchResultDTO[]; // Could include relevance scores 76 pagination: PaginationInfo; 77 searchMetadata: { 78 query: string; 79 totalMatches: number; 80 searchTime?: number; 81 }; 82} 83``` 84 85**Changes Required**: 86 87- Create new `SearchMyCollectionsUseCase` 88- Create new repository method or separate search repository 89- Create new HTTP controller and route 90- Update API client with new search method 91- Implement search-specific DTOs 92 93### Option 3: Hybrid Approach 94 95**Pattern**: Extend existing use case but add dedicated search endpoint 96 97**Implementation**: 98 99- Keep enhanced `GetMyCollectionsUseCase` for general listing with optional search 100- Add dedicated `SearchMyCollectionsUseCase` for advanced search features 101- Both share the same underlying repository search capability 102 103## Recommended Approach: Option 1 (Extended Query) 104 105### Rationale 106 1071. **Consistency**: Aligns with existing patterns where query use cases handle filtering/searching 1082. **Simplicity**: Single endpoint for both listing and searching collections 1093. **Client Efficiency**: No need to switch between different API methods 1104. **Future-Proof**: Easy to add more filter parameters later 111 112### Implementation Plan 113 114#### 1. Domain Layer Updates 115 116```typescript 117// Update ICollectionQueryRepository interface 118export interface CollectionQueryOptions { 119 page: number; 120 limit: number; 121 sortBy: CollectionSortField; 122 sortOrder: SortOrder; 123 searchText?: string; // NEW 124} 125``` 126 127#### 2. Application Layer Updates 128 129```typescript 130// Update GetMyCollectionsQuery 131export interface GetMyCollectionsQuery { 132 curatorId: string; 133 page?: number; 134 limit?: number; 135 sortBy?: CollectionSortField; 136 sortOrder?: SortOrder; 137 searchText?: string; // NEW 138} 139``` 140 141#### 3. Infrastructure Layer Updates 142 143- Update `DrizzleCollectionQueryRepository.findByCreator()` to handle text search 144- Implement SQL text search (LIKE, full-text search, or similar) 145- Update HTTP controller to accept search parameter 146- Update route parameter handling 147 148#### 4. API Client Updates 149 150```typescript 151// Update existing types 152export interface GetMyCollectionsParams { 153 page?: number; 154 limit?: number; 155 sortBy?: string; 156 sortOrder?: 'asc' | 'desc'; 157 searchText?: string; // NEW 158} 159 160// No new methods needed - existing getMyCollections() handles search 161``` 162 163### Search Implementation Details 164 165#### Database Search Strategy 166 167```sql 168-- Example SQL for text search across name and description 169SELECT * FROM collections 170WHERE curator_id = ? 171 AND ( 172 name ILIKE '%search_term%' 173 OR description ILIKE '%search_term%' 174 ) 175ORDER BY name ASC 176LIMIT ? OFFSET ?; 177``` 178 179#### Search Behavior 180 181- **Empty/null search**: Return all collections (existing behavior) 182- **Search scope**: Collection name and description fields 183- **Search type**: Case-insensitive partial matching (can be enhanced later) 184- **Sorting**: Maintain existing sort options, could add relevance sorting later 185 186### Migration Path 187 1881. Update domain interfaces (backward compatible) 1892. Update use case (backward compatible - search is optional) 1903. Update repository implementation 1914. Update HTTP layer 1925. Update API client types 1936. Update frontend components 194 195This approach provides immediate value while maintaining architectural consistency and leaving room for future enhancements like advanced search features, search analytics, or dedicated search optimization.