Wie sieht ein Datenmodell für ein Forum aus?
Verfasst: Sonntag 2. März 2008, 12:25
Wie sieht eigentlich das Datenmodell einer typischen Forumsanwendung aus, speziell wenn ich es auf Django abbilden will? Mir geht es insbesondere darum, wie ich ungelesene und gelesene Beiträge verwalte. Dazu muss ich jedoch erstmal weiter ausholen.
Ein Forum (Forum) habe Themen (Topic) und jedes Thema habe Beiträge (Post). Ein Forum habe außerdem Benutzer (User), die Beiträge schreiben.
Anzeigen möchte ich gerne alle Foren in definierbarer Reihenfolge (hier egal), die Anzahl der Themen und Beiträge (auch egal, würde man wohl de-normalisieren und diese Zahlen im Forum speichern statt jedes mal zu zählen) und möglicherweise wer zuletzt was geschrieben hat (nochmal egal). Für jedes Forum möchte ich die Themen sortiert nach dem letzten Beitrag anzeigen, die Anzahl der Beiträge pro Thema und wer zuletzt was gechrieben hat (egal). Für jedes Thema möchte ich die Beiträge mit ihren Autoren anzeigen.
So weit, so gut.
Für jeden User möchte ich nun festhalten, welche Beiträge er gesehen hat bzw. welche noch neu für ihn sind. Wie mache ich dies und insbesondere, wie mache ich dies einigermaßen speichereffizient?
Der naive Ansatz wäre wohl, pro User und Thema einen Eintrag in einer speziellen Tabelle abzulegen. Entweder
oder
Wenn aber wie in diesem Forum bereits über 12.000 Themen existieren und dann vielleicht noch 5.000 Anwender, hätte ich 60.000.000 Datensätze für gelesene Themen. Zu viel!
Speichere ich die ungelesenen Themen, müsste ich bei jeder Änderung hier pro Anwender einen Datensatz schreiben und später diese wieder löschen. Sagen wir einmal, das pro Tag 40 Beiträge geschrieben werden (was ungefähr für dieses Forum hinkommt) und User 1x pro Woche lesen, dann sind es noch 1.400.000 Datensätze. Hm.
Ich möchte allerdings nicht einfach nur ablegen, wann der letzte Login war, um dann alles, was seit diesem Zeitpunkt neu ist, zu markieren. Ich hasse, wenn Foren vergessen, was ich noch nicht gelesen habe (dieses Forum macht es auch manchmal).
Ich könnte die Menge der Datensätze reduzieren, indem ich die Informationen kompakt kodiere. Pro Forum könnte ich die Information, welche Themen bis zu welchen Beiträgen gelesen wurden, in einem String ablegen.
Bei etwa 200 Themen pro Forum und 12 Zeichen pro Paar kommen wir auf 2400 Zeichen pro Forum und Anwender. Letztlich die selbe Informationsmenge, aber vielleicht kann ich's so effizienter speichern als die Datenbank in Tabellen.
Wenn ich Beiträge nicht global durchnummeriere, sondern pro Forum, kann ich die Liste verkürzen, indem ich ausnutze, dass in der Regel das Gros der Beiträge bekannt ist und ich ein (offene) Intervale benutze, die Beiträge aufzuzählen:
Nun habe ich aber ein Problem mit Django, welches keine zusammengesetzten Primärschlüssel unterstützt und ich damit dann keine Beiträge mehr haben kann, die durch id + forum_id erst eindeutig werden.
Es muss doch einen besseren Ansatz geben!
Stefan
Ein Forum (Forum) habe Themen (Topic) und jedes Thema habe Beiträge (Post). Ein Forum habe außerdem Benutzer (User), die Beiträge schreiben.
Code: Alles auswählen
class User(models.Model):
"""Represents a forum user who writes posts."""
name = models.CharField()
class Forum(models.Model):
"""Represents a list of related conversations."""
title = models.CharField()
class Topic(models.Model):
"""Represents a single conversation consisting of postings."""
title = models.CharField()
forum = models.ForeignKey(Forum, related_name='topics')
class Post(models.Model):
body = models.TextField()
date = models.DateTimeField()
author = models.ForeignKey(User, related_name='all_posts')
topic = models.ForeignKey(Topic, related_name='posts')
So weit, so gut.
Für jeden User möchte ich nun festhalten, welche Beiträge er gesehen hat bzw. welche noch neu für ihn sind. Wie mache ich dies und insbesondere, wie mache ich dies einigermaßen speichereffizient?
Der naive Ansatz wäre wohl, pro User und Thema einen Eintrag in einer speziellen Tabelle abzulegen. Entweder
Code: Alles auswählen
class Read(models.Model):
topic = models.ForeignKey(Topic)
user = models.ForeignKey(User)
Code: Alles auswählen
class Unread(models.Model):
topic = models.ForeignKey(Topic)
user = models.ForeignKey(User)
Speichere ich die ungelesenen Themen, müsste ich bei jeder Änderung hier pro Anwender einen Datensatz schreiben und später diese wieder löschen. Sagen wir einmal, das pro Tag 40 Beiträge geschrieben werden (was ungefähr für dieses Forum hinkommt) und User 1x pro Woche lesen, dann sind es noch 1.400.000 Datensätze. Hm.
Ich möchte allerdings nicht einfach nur ablegen, wann der letzte Login war, um dann alles, was seit diesem Zeitpunkt neu ist, zu markieren. Ich hasse, wenn Foren vergessen, was ich noch nicht gelesen habe (dieses Forum macht es auch manchmal).
Ich könnte die Menge der Datensätze reduzieren, indem ich die Informationen kompakt kodiere. Pro Forum könnte ich die Information, welche Themen bis zu welchen Beiträgen gelesen wurden, in einem String ablegen.
Code: Alles auswählen
12812:4522,12813:4598 # Topic:Post,Topic:Post,...
Wenn ich Beiträge nicht global durchnummeriere, sondern pro Forum, kann ich die Liste verkürzen, indem ich ausnutze, dass in der Regel das Gros der Beiträge bekannt ist und ich ein (offene) Intervale benutze, die Beiträge aufzuzählen:
Code: Alles auswählen
4528,4522-4518,4507- # ID oder ID2-ID1 oder ID-
Es muss doch einen besseren Ansatz geben!
Stefan