Sobes.tech
Senior

/* Jeste pisarzem, prowadzisz swój mini blog i tam publikujesz artykuły. Użytkownicy (czytelnicy) twojego bloga, po zalogowaniu się, mogą je przeglądać/czytać. Należy zaimplementować funkcjonalność liczenia unikalnych wyświetleń dziennie dla każdego artykułu. Wymagania funkcjonalne: - Statystyki za dzisiaj: Autor może zobaczyć, ilu unikalnych użytkowników obejrzało jego artykuł dzisiaj (dane są zbierane w czasie rzeczywistym). - Statystyki za minione dni: Autor może zobaczyć statystyki za dowolny miniony dzień (np. wczoraj). Ograniczenia techniczne i warunki: - Aplikacja działa na jednym serwerze (jednym podzie) - Przechowywanie w pamięci - Czas w UTC0 */

sobes.tech AI

Odpowiedź od AI

Aby zliczyć unikalne wyświetlenia artykułów dziennie, przechowując dane w pamięci i korzystając z jednego serwera, można użyć następującej struktury:

  • Dla każdego dnia (według daty UTC) przechowywać mapę: map[articleID]map[userID]bool, gdzie klucze to ID artykułu i ID użytkownika.
  • Przy oglądaniu artykułu przez zalogowanego użytkownika, dodać userID do mapy dla odpowiedniego artykułu i bieżącej daty.
  • Aby uzyskać statystyki na dziś lub wczoraj, policzyć długość wewnętrznej mapy użytkowników dla artykułu.

Przykład w Go:

type Stats struct {
    mu sync.RWMutex
    data map[string]map[string]map[string]bool // data -> ID artykułu -> ID użytkownika -> bool
}

func NewStats() *Stats {
    return &Stats{data: make(map[string]map[string]map[string]bool)}
}

func (s *Stats) AddView(articleID, userID string) {
    s.mu.Lock()
    defer s.mu.Unlock()
    date := time.Now().UTC().Format("2006-01-02")
    if s.data[date] == nil {
        s.data[date] = make(map[string]map[string]bool)
    }
    if s.data[date][articleID] == nil {
        s.data[date][articleID] = make(map[string]bool)
    }
    s.data[date][articleID][userID] = true
}

func (s *Stats) GetUniqueViews(articleID, date string) int {
    s.mu.RLock()
    defer s.mu.RUnlock()
    if s.data[date] == nil || s.data[date][articleID] == nil {
        return 0
    }
    return len(s.data[date][articleID])
}

Ten sposób pozwala na zbieranie unikalnych wyświetleń w czasie rzeczywistym i uzyskiwanie statystyk dla dowolnego dnia. W razie potrzeby można dodać okresowe czyszczenie starych danych, aby nie zużywać zbyt dużo pamięci.