Add performance optimizations and database indexes
Database Indexes (migrations 006-009): - Add case-insensitive indexes for auth lookups (email, username) - Add composite indexes for task kanban queries - Add indexes for notification, document, and completion queries - Add unique index for active share codes - Remove redundant idx_share_code_active and idx_notification_user_sent Repository Optimizations: - Add FindResidenceIDsByUser() lightweight method (IDs only, no preloads) - Optimize GetResidenceUsers() with single UNION query (was 2 queries) - Optimize kanban completion preloads to minimal columns (id, task_id, completed_at) Service Optimizations: - Remove Category/Priority/Frequency preloads from task queries - Remove summary calculations from CRUD responses (client calculates) - Use lightweight FindResidenceIDsByUser() instead of full FindByUser() These changes reduce database load and response times for common operations. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -67,6 +67,24 @@ func (r *ResidenceRepository) FindByUser(userID uint) ([]models.Residence, error
|
||||
return residences, nil
|
||||
}
|
||||
|
||||
// FindResidenceIDsByUser returns just the IDs of residences a user has access to.
|
||||
// This is a lightweight alternative to FindByUser() when only IDs are needed.
|
||||
// Avoids preloading Owner, Users, PropertyType relations.
|
||||
func (r *ResidenceRepository) FindResidenceIDsByUser(userID uint) ([]uint, error) {
|
||||
var ids []uint
|
||||
err := r.db.Model(&models.Residence{}).
|
||||
Where("is_active = ?", true).
|
||||
Where("owner_id = ? OR id IN (?)",
|
||||
userID,
|
||||
r.db.Table("residence_residence_users").Select("residence_id").Where("user_id = ?", userID),
|
||||
).
|
||||
Pluck("id", &ids).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ids, nil
|
||||
}
|
||||
|
||||
// FindOwnedByUser finds all residences owned by a user
|
||||
func (r *ResidenceRepository) FindOwnedByUser(userID uint) ([]models.Residence, error) {
|
||||
var residences []models.Residence
|
||||
@@ -118,42 +136,41 @@ func (r *ResidenceRepository) RemoveUser(residenceID, userID uint) error {
|
||||
).Error
|
||||
}
|
||||
|
||||
// GetResidenceUsers returns all users with access to a residence
|
||||
// GetResidenceUsers returns all users with access to a residence (owner + shared users).
|
||||
// Optimized: Uses a single UNION query instead of preloading full residence with relations.
|
||||
func (r *ResidenceRepository) GetResidenceUsers(residenceID uint) ([]models.User, error) {
|
||||
residence, err := r.FindByID(residenceID)
|
||||
var users []models.User
|
||||
// Single query to get both owner and shared users
|
||||
err := r.db.Raw(`
|
||||
SELECT DISTINCT u.* FROM auth_user u
|
||||
WHERE u.id IN (
|
||||
SELECT owner_id FROM residence_residence WHERE id = ? AND is_active = true
|
||||
UNION
|
||||
SELECT user_id FROM residence_residence_users WHERE residence_id = ?
|
||||
)
|
||||
`, residenceID, residenceID).Scan(&users).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
users := make([]models.User, 0, len(residence.Users)+1)
|
||||
users = append(users, residence.Owner)
|
||||
users = append(users, residence.Users...)
|
||||
return users, nil
|
||||
}
|
||||
|
||||
// HasAccess checks if a user has access to a residence
|
||||
func (r *ResidenceRepository) HasAccess(residenceID, userID uint) (bool, error) {
|
||||
var count int64
|
||||
|
||||
// Check if user is owner
|
||||
err := r.db.Model(&models.Residence{}).
|
||||
Where("id = ? AND owner_id = ? AND is_active = ?", residenceID, userID, true).
|
||||
Count(&count).Error
|
||||
// Single query using UNION to check owner OR member access
|
||||
err := r.db.Raw(`
|
||||
SELECT COUNT(*) FROM (
|
||||
SELECT 1 FROM residence_residence
|
||||
WHERE id = ? AND owner_id = ? AND is_active = true
|
||||
UNION
|
||||
SELECT 1 FROM residence_residence_users
|
||||
WHERE residence_id = ? AND user_id = ?
|
||||
) access_check
|
||||
`, residenceID, userID, residenceID, userID).Scan(&count).Error
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if count > 0 {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// Check if user is in shared users
|
||||
err = r.db.Table("residence_residence_users").
|
||||
Where("residence_id = ? AND user_id = ?", residenceID, userID).
|
||||
Count(&count).Error
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return count > 0, nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user