Architektura bazy danych dla systemu "Badge" i dowolne kryteria (MySQL / PHP)

Quickie-Pytanie:

Podsumowując, jestem trochę zdezorientowany co do tego, jak zaprojektowałbym taką bazę danych, która pozwala na tworzenie nieograniczonych reguł znaczków bez konieczności wprowadzania zmian strukturalnych do wcześniej istniejących tabel użytkowników w bazie danych.

Przechowywanie tytułu odznaki, kryteriów itp. Jak wyglądałby Ten stół?

  • badge_id (1)
  • badge_title (10k Badge)
  • badge_image (10k.jpg)
  • badge_criteria ([posts] >= 10000)
    ...

Winded-Pytanie:

Chciałbym wdrożyć system odznak w moich osobistych projektach, ale szukam porady, jak najlepiej zrobić coś takiego. Czytałem kilka pytań na temat systemów odznak, ale nie widzę, aby Architektura bazy danych przyciągała uwagę.

Odznaki oparte na punktach użytkownika (hipotetyczna "Odznaka 10k") wydawałyby się całkiem proste. Każde zdarzenie, które wpływa na reputację użytkowników (upvotes, downvotes, answer-accepted, etc) wywoła metodę, aby sprawdzić nową reputację użytkowników i potencjalnie przyznać odznakę.

Ten system brzmi dość prosto, ale jak to wygląda jako baza danych dla administratora, który chce tworzyć niezliczone ilości odznak przy niewielkim wysiłku w dół drogi - niektóre z nich mogą być oparte na różnych kryteriach, a nie tylko reputacji użytkownika.

Reputacja użytkownika jest prawdopodobnie wartością w samym rekordzie użytkownika. Ale czy nie chciałbyś uniknąć konieczności dodawania nowych pól do tabeli użytkowników podczas tworzenia nowych odznak? Na przykład znaczek "Edited 100 Entries" - nie utworzyłbyś nowej kolumny "entries_edited" w tabeli Users, prawda? A następnie Zwiększa to po każdym wpisie-edytowane... Jakieś wskazówki?

Archiwum Stoskoverflow:


uwaga: nie pytam, jak powiązać odznaki z użytkownikami. Nie pytam jak przyznawać odznaki (to będzie zrobione programowo)

Author: Community, 2009-06-26

7 answers

Biorąc pod uwagę, że kryteria odznaki mogą być arbitralnie złożone, nie sądzę, że można je przechowywać w tabeli bazy danych z podziałem na "proste" elementy danych. Próba napisania "silnika reguł", który może obsługiwać arbitralnie złożone kryteria, zabierze cię w dół drogi do zasadniczo ponownego pisania wszystkich narzędzi, które masz w swoim języku programowania.

Jeśli z góry wiesz, że chcesz, aby odznaki były ograniczone tylko do określonych pól (np. odznaki są oparte tylko na reputacji lub liczbie edycji czy coś), wtedy można je zapisać w prostej tabeli jak:

ReputationBadgeCriteria
  BadgeId
  BadgeName
  MinReputation

Alternatywnie, możesz użyć jakiegoś DSL do napisania swoich "reguł", ale w końcu musisz również utworzyć parser do analizy reguł podczas ich czytania, jak również coś do wykonania tych reguł. W zależności od złożoności, jaką chcesz w DSL, może to nie być trywialne zadanie. Wygląda to jak ścieżka, którą idziesz w swoim pytaniu z kolumną kryteriów (prawdopodobnie zwykły tekst), która ma coś w rodzaju "[Reputacja] > 1000" lub "[posty] > 5 " w nim. Nadal musisz przeanalizować i wykonać te reguły, a złożoność napisania czegoś w tym celu zależy od tego, jak skomplikowane mają być te reguły.

Polecam przeczytać tecodziennie WTF artykuły aby dowiedzieć się, dlaczego takie podejście prowadzi do bólu.

 23
Author: David Archer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-26 14:17:47

W zależności od tego, jak daleko chcesz iść z nim, Twój schemat może być dość skomplikowane. Wydaje mi się, że podstawowe elementy, które musisz śledzić, to:

Badges awarded
Points earned

Jak na razie dość proste, ale chcesz być w stanie dynamicznie tworzyć nowe odznaki i nowe kategorie punktów. Przyznawanie odznak zależałoby od zdobywania punktów w jednej lub kilku kategoriach punktowych, które sumowałyby się do określonej kwoty. Musisz więc śledzić relacje między kategoriami punktowymi (i uzyskanymi punktami) i odznaki:

Point categories
Badge categories

Więc kluczem będzie Tabela punktów użytkownika, która łączy się z kategoriami punktów, które łączą się z odznakami. Użytkownicy zdobywają punkty w danej kategorii, co przyczyniłoby się do zdobycia punktów na jedną lub więcej odznak.

badges:
badge_id
badge_name
required_points
....

point_categories:
point_id
category_name
weighting (optional)
...

point_groups:
badge_id
point_id
weighting (optional)
...

user_points:
user_id
point_id
points
...

user_badges:
user_id
badge_id
points_earned
badge_awarded (yes/no)
...

Twój interfejs "admin" pozwoliłby komuś stworzyć nową odznakę i wybrać kategorie punktów, które są wymagane do zdobycia tej odznaki (point_groups). Za każdym razem, gdy użytkownik zdobywa punkty (user_points), aktualizujesz tabelę user_points, a następnie określasz do których odznak te punkty mogłyby się przyczynić (point_groups). Następnie przekompilujesz punkty za odznaki, na które wpłynęły zdobyte punkty i zaktualizujesz tabelę user_badges o point_earned. Następnie sprawdź pole points_earned w user_badges względem required_points w tabeli badges.

Możesz uzyskać więcej fantazji, przypisując różne wagi do różnych kategorii punktowych, a nawet różne wagi dla kategorii punktowych dla poszczególnych odznak. Ale taka konfiguracja umożliwia tworzenie i zarządzanie nieograniczoną liczbą odznak i kategorii punktów bez zmiany struktur tabel.

Jeśli to nie jest to, czego szukasz, to myślę, że powinienem przynajmniej dostać głos lub dwa za dużo typowania.

 19
Author: Brent Baisley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-26 15:12:29

Możesz śledzić swoich unikalnych użytkowników w jednej tabeli i unikalnych odznak w innej, a następnie utworzyć tabelę odsyłaczy, aby je powiązać.

Użytkownik może mieć wiele odznak, a odznaka może mieć wielu użytkowników.

create table users (
id int,
name varchar
)

create table badges (
id int,
badge_name varchar
)


create table user_badges_xref (
user_id int,
badge_id int
)

Statystyki, które mogą mieć wpływ na to, czy użytkownik zdobędzie odznakę, są śledzone w ramach administracji witryny. więc coś takiego jak odpowiedź jest akceptowane byłoby w schemacie, który dotyczy pytania i odpowiedzi. w celu wyświetlenia odpowiedzi i właściciela odpowiedzi, istnieje związek z tabelą użytkownika i wyzwalaczami, które sprawdzałyby warunki odznaki za każdym razem, gdy dokonano zmiany.

Nie pytam, jak przyznawać odznaki. Pytam jak przechowywać kryteria w bazie danych.

Więc chcesz zapisać logiczną operację wymaganą do ustalenia, czy odznaka jest zdobyta gdzieś w polu?

Myślę, że Zgadzam się z innym plakatem, że kryteria powinny być częścią logiki biznesowej. Że logika może być w aplikacji z boku lub wewnątrz spustu. Myślę, że to kwestia stylu.

Gdybyś naprawdę był mężem idei przechowywania kryteriów w polu, przechowywałbym je jako parametryzowany SQL i uruchamiał dynamicznie.

Więc takie rzeczy byłyby w twoim polu kryteriów:

select "Badge Earned"
from all_posts 
where user_id = @user_id
having count(*) > 10000
 5
Author: Bob Probst,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-26 14:37:46

Nie tworzyłbym przyrostu dla znaczka edycji. Myślę, że powinieneś mieć zadanie działające w tle i liczyć () liczbę edytowanych postów dla członków, którzy nie mają jeszcze odznaki edycji. Gdy zobaczysz, że liczba przekroczyła żądany zakres, dodajesz do bazy danych wpis informujący o tym, że użytkownik ma odznakę.

Myślę, że to samo dotyczy innych odznak. Staraj się ograniczyć liczbę napisów i nie zapisuj bezpośrednio informacji o liczbie plakietek w tabela użytkowników. Użyj tabeli, która będzie zawierać informacje o plakietce i połącz ją z tabelą użytkownika.

 3
Author: Patrick Desjardins,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-26 13:50:56

Przepraszam za zwięzłość.

Aby zaimplementować taki system, mogę utworzyć tabelę, która przechowuje nazwy procedur składowanych lub rzeczywiste zapytania, które będą używane do określenia, czy dany użytkownik zdobył odznakę.

badge_criteria
badge_key int
badge_criteria varchar(max)

Możesz wyodrębnić i wykonać zapytania o odznaki, których Użytkownik nie zdobył z poziomu średniego, ale nie będziesz musiał wprowadzać żadnych zmian w kodzie ani strukturze, aby dodawać nowe odznaki.

 3
Author: Christian Pena,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-26 14:47:01

Podchodzę do tego w następujący sposób: stwórz tabelę do przechowywania wszystkich odznak, i miej jedną kolumnę odwołującą się do funkcji, która jest uruchamiana, aby sprawdzić, czy odznaka jest przyznawana. W ten sposób tabela pozostaje prosta, a logika określania odznak może być zachowana w kodzie, gdzie jest najlepiej dopasowana.

Dzięki tej metodzie wymagania badge mogą być również połączone ze sobą, tworząc bardziej złożone zależności. Na przykład, użytkownik musi otrzymać trzy oddzielne, specyficzne odznaki w / w określonym terminie, aby zdobądź odznakę.

 3
Author: Tapefreak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-02 21:29:51

To będzie prawie niemożliwe do zrobienia w bazie danych - przyznawanie odznak powinno odbywać się w logice biznesowej w aplikacji. W ten sposób masz wszystkie potrzebne dane (edycje, wizyty, reputacja itp.) i można sobie z tym poradzić tak, jak uważasz za stosowne.

Aktualizacja:

Jeśli przez kryteria rozumie się zasady określające czy i w jaki sposób odznaka jest przyznawana, to nie jest to coś, co powinno być przechowywane w bazie danych. Byłoby to prawie niemożliwe do przetestowania i utrzymać.

Jeśli masz na myśli na przykład przechowywanie "liczby edycji", nie ma możliwości obejścia modyfikacji tabeli lub procedury składowanej, aby uwzględnić te dane, jeśli tego potrzebujesz.

 2
Author: John Rasch,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-26 14:01:20