Frage

Ich frage mich, was der beste Weg wäre, eine soziale Anwendung zu entwerfen, in denen die Mitglieder Aktivitäten machen und andere Aktivitäten der Mitglieder mit Google App Engine folgen.

Um genauer sein, lässt vermuten, wir haben diese Entitäten:

  • Nutzer , die Freunde
  • haben
  • Aktivitäten , die von anderen Nutzern gemacht Aktionen darstellen (können sagen, jeder hat eine String-Nachricht und eine Reference zu seinem Besitzer Benutzer, oder es kann Elternvereinigung über appengine der Taste)

Der harte Teil Ihres Freundes Aktivitäten verfolgt, das heißt, die neuesten Aktivitäten von allen Ihren Freunden aggregieren. Normalerweise würde, dass eine Liste der Tätigkeiten Tisch und Ihre Freunde beitreten, aber das ist nicht ein lebensfähiges Design auf appengine, da es keine join simuliert es N-Abfragen Anheizen benötigt (wobei N Anzahl von Freunden) und dann im Speicher verschmelzenden - sehr teuer und wird wahrscheinlich Anfrage Frist überschreiten ...)

Ich denke zur Zeit diese Posteingang Warteschlangen mit der Implementierung, wo Schaffung einer neuen Aktivität wird ein Hintergrundprozess Feuer, das die neue Tätigkeit der Schlüssel in der „Posteingang“ eines jeden folgenden Benutzer gesetzt werden:

  • Ankommen „Alle Nutzer, die X folgen“ ist eine mögliche appengine Abfrage
  • Nicht eine sehr teuere Batch-Input in eine neue „Posteingang“ Einheit, die im Grunde speichert (Benutzer, Aktivität Key) Tupel.

Ich werde gehört Gedanken auf diesem Entwurf oder alternative Vorschläge gerne etc.

War es hilfreich?

Lösung

Hier finden Sie aktuelle Gebäude Skalierbare, Komplexe Apps auf App Engine ( pdf ), ein faszinierender Vortrag bei Google I / O von Brett Slatkin gegeben. Er befasst sich mit dem Problem der Bereitstellung einer skalierbaren Messaging-Dienst wie Twitter zu bauen.

Hier ist seine Lösung mit einer Liste Eigenschaft:

class Message(db.Model):
    sender = db.StringProperty()
    body = db.TextProperty()

class MessageIndex(db.Model):
    #parent = a message
    receivers = db.StringListProperty()

indexes = MessageIndex.all(keys_only = True).filter('receivers = ', user_id)
keys = [k.parent() for k in indexes)
messages = db.get(keys)

Dieser Schlüssel nur Abfrage findet die Nachrichten Indizes mit einem Empfänger gleich dem Sie ohne Deserialisieren angegeben und die Liste der Empfänger der Serialisierung. Dann Sie diese Indizes verwenden, um nur die Nachrichten greifen, die Sie wollen.

Hier die falsche Art und Weise , es zu tun:

class Message(db.Model):
    sender = db.StringProperty()
    receivers = db.StringListProperty()
    body = db.TextProperty()

messages = Message.all().filter('receivers =', user_id)

Dies ist ineffizient, da Abfragen alle Ergebnisse durch Ihre Frage zurück auszupacken haben. Also, wenn Sie 100 Nachrichten mit 1.000 Benutzern in jedem Empfänger Liste zurückgegeben würden Sie 100.000 (100 x 1000) Liste Eigenschaftswerte deserialisieren haben. Viel zu teuer in Datenspeicher-Latenz und CPU.

Ich war ziemlich durch all dies zunächst verwirrt, so schrieb ich, um eine kurzes Tutorial über die Liste Eigenschaft verwenden. Genießen Sie:)

Andere Tipps

Ich weiß nicht, ob es das am besten Design für eine soziale Anwendung, aber jaiku WAS auf App Engine portiert von seinem ursprünglichen Schöpfer ist, wenn das Unternehmen von Google übernommen wurde, so sollte es sinnvoll sein.

Im Abschnitt Schauspieler und Tiger und Bären, oh meine! in design_funument.txt . Die Objekte werden in / models.py und die Abfragen sind in / api.py .

Robert, über Ihre vorgeschlagene Lösung:

messages = Message.query(Message.receivers == user_id).fetch(projection=[Message.body])

Ich denke, der ndb.TextProperty „Körper“ kann nicht mit Projektionen verwendet werden, da nicht indiziert. Projektionen nur indizierte Eigenschaften unterstützen. Die gültige Lösung wäre es, die zwei Tabellen zu pflegen. Nachricht und message

Ich denke, das kann jetzt mit den neuen Projektions-Abfragen in NDB gelöst werden.

class Message(ndb.Model):
    sender = ndb.StringProperty()
    receivers = ndb.StringProperty(repeated=True)
    body = ndb.TextProperty()

messages = Message.query(Message.receivers == user_id).fetch(projection=[Message.body])

Jetzt müssen Sie nicht mit den teuer Kosten für Deserialisieren der Liste Eigenschaft befassen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top