Frage Viele zu viele Beziehungen mit MongoDB in großem Maßstab


Ich habe viele Beiträge darüber gesehen, wie man viele-zu-viele-Beziehungen mit MongoDB herstellen kann, aber keiner von ihnen erwähnt Skalierung. Zum Beispiel diese Beiträge:

MongoDB Many-to-Many-Vereinigung

Wie man eine viele zu viele Beziehung in MongoDB organisiert

Das Problem, das ich mit dieser Art von Setup sehen kann, ist MongoDB's 16MB Dokumentenlimit. Sag ich habe users, groups und posts. posts haben einen Zusammenhang group und viele users das kann es mögen. EIN group hat viele posts drin und viele users, die ihm folgen können. EIN user kann viele mögen posts und kann viele folgen groups. Wenn ich dies mit einer relationalen Datenbank erstellen würde, würde ich es so einrichten:

user:
    user_id
    username

post:
    post_id
    group_id
    message

group:
    group_id
    name

post_likes:
    post_id
    liked_user_id

group_followers:
    group_id
    follower_user_id

In der Theorie a group kann eine begrenzte Anzahl von haben posts und folgende users, a post kann eine unbegrenzte Anzahl von gemocht haben users und a user kann eine unbegrenzte Anzahl von gemocht haben posts und groups, denen sie folgen, wenn die Paginierung in den SQL-Abfragen korrekt ausgeführt wird.

Wie kann ich das MongoDB-Schema einrichten, damit diese Art von Skalierung erreicht werden kann?


5
2017-08-08 01:32


Ursprung


Antworten:


Dies ist eine gute Frage, die die Probleme mit Überbelastungen und den Umgang damit verdeutlicht.

Beispiel: Likes veröffentlichen

Bleiben wir beim Beispiel der Benutzer, die Beiträge mögen, was ein einfaches Beispiel ist. Die anderen Beziehungen müssten entsprechend behandelt werden.

Sie haben absolut Recht, dass mit dem Speichern der Likes in der Post früher oder später zu dem Problem führen würde, dass sehr populäre Beiträge die Größenbeschränkung erreichen würden.

Du bist also richtig zurück gefallen um ein zu erstellen post_likes Sammlung. Warum nenne ich das korrekt? Da passt es zu Ihren Anwendungsfällen und funktionalen und nicht-funktionalen Anforderungen!

  • Es skaliert indefinetly (gut, es gibt eine theoretische Grenze, aber es ist humongous)
  • Es ist einfach zu pflegen (erstellen Sie einen eindeutigen Index über post_id und liked_user_id) und verwenden (sowohl der Benutzer als auch der Post sind bekannt, also ist das Hinzufügen eines Gleichen ein einfacher Eintrag oder wahrscheinlicher ein Upsert)
  • Sie können leicht herausfinden, welche Benutzer welche Post mögen und welche Post von welchen Benutzern gemocht wird

Allerdings würde ich die Sammlung ein wenig erweitern, um unnötige Abfragen für bestimmte Anwendungsfälle zu vermeiden, die häufig sind.

Nehmen wir an, dass Posttitel und Benutzernamen nicht geändert werden können. In diesem Fall könnte das folgende Datenmodell sinnvoller sein

{
  _id: new ObjectId(),
  "post_id": someValue,
  "post_title": "Cool thing",
  "liked_user_id": someUserId,
  "user_name": "JoeCool"
}

Angenommen, Sie möchten den Nutzernamen aller Nutzer anzeigen, die einen Beitrag mochten. Mit dem obigen Modell wäre das eine einzelne, ziemlich schnelle Abfrage:

db.post_likes.find(
  {"postId":someValue},
  {_id:0,user_name:1}
)

Wenn nur die IDs gespeichert sind, würde diese eher übliche Aufgabe mindestens zwei Abfragen und - angesichts der Einschränkung, dass es unendlich viele Likers für einen Post geben kann - potentiell benötigen enorm Speicherverbrauch (Sie müssten die Benutzer-IDs im Arbeitsspeicher speichern).

Zugegeben, das führt zu einiger Redundanz, aber selbst wenn Millionen von Leuten einen Post mögen, sprechen wir nur von ein paar Megabyte relativ günstigem (und einfach zu skalierendem) Plattenplatz beim Gewinnen viel Leistung in Bezug auf die Benutzerfreundlichkeit.

Jetzt kommt die Sache: Auch wenn sich die Benutzernamen und Titel ändern können, mussten Sie nur ein Multi-Update durchführen:

db.post_likes.update(
  {"post_id":someId},
  { $set:{ "post_title":newTitle} },
  { multi: true}
)

Sie handeln damit, dass es eine Weile dauert, einige ziemlich seltene Dinge wie die Änderung eines Benutzernamens oder eines Posts für extreme Geschwindigkeit für Anwendungsfälle zu tun, die extrem oft vorkommen.

Endeffekt

Denken Sie daran, dass MongoDB eine dokumentenorientierte Datenbank ist. Dokumentieren Sie die Ereignisse, an denen Sie interessiert sind, mit den Werten, die Sie für zukünftige Abfragen benötigen, und modellieren Sie Ihre Daten entsprechend.


7
2017-08-08 09:13



Wenn Sie nur die IDs der Beziehungen in den Arrays der Reach-Sammlung speichern, sollten Sie innerhalb eines Dokuments nicht viel Probleme haben. GridFS kann verwendet werden, aber das ist in der Regel mehr für Medien wie Dateien, Musik, Videos, etc. mit GridFS machen Updates zu einem Schmerz


0
2017-08-08 02:16