MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Wie man mit MongoDB ein Like-Voting-System modelliert

Unabhängig davon, wie Sie Ihr gesamtes Dokument strukturieren, benötigen Sie im Wesentlichen zwei Dinge. Das ist im Grunde eine Eigenschaft für eine "Zählung" und eine "Liste" derer, die bereits ihr "Gefällt mir" gepostet haben, um sicherzustellen, dass keine Duplikate eingereicht werden. Hier ist eine grundlegende Struktur:

{ 
    "_id": ObjectId("54bb201aa3a0f26f885be2a3")
    "photo": "imagename.png",
    "likeCount": 0
    "likes": []
}

Wie auch immer, es gibt eine eindeutige "_id" für Ihren "Fotobeitrag" und alle gewünschten Informationen, aber dann die anderen Felder wie erwähnt. Die Eigenschaft „likes“ ist hier ein Array, das die eindeutigen „_id“-Werte der „user“-Objekte in Ihrem System enthalten wird. Jeder "Benutzer" hat also irgendwo seine eigene eindeutige Kennung, entweder im lokalen Speicher oder OpenId oder so, aber eine eindeutige Kennung. Ich bleibe bei ObjectId für das Beispiel.

Wenn jemand einem Beitrag ein "Gefällt mir" sendet, möchten Sie die folgende Aktualisierungserklärung abgeben:

db.photos.update(
    { 
        "_id": ObjectId("54bb201aa3a0f26f885be2a3"), 
        "likes": { "$ne": ObjectId("54bb2244a3a0f26f885be2a4") }
    },
    {
        "$inc": { "likeCount": 1 },
        "$push": { "likes": ObjectId("54bb2244a3a0f26f885be2a4") }
    }
)

Nun der $inc Operation dort wird den Wert von "likeCount" um die angegebene Zahl erhöhen, also um 1 erhöhen. Der $push Die Operation fügt den eindeutigen Bezeichner für den Benutzer zum Array im Dokument hinzu, um später darauf zurückgreifen zu können.

Das Wichtigste hier ist, aufzuzeichnen, welche Benutzer abgestimmt haben und was im "Abfrage"-Teil der Erklärung passiert. Abgesehen von der Auswahl des zu aktualisierenden Dokuments anhand seiner eigenen eindeutigen "_id", ist die andere wichtige Sache, das "likes"-Array zu überprüfen, um sicherzustellen, dass der aktuelle abstimmende Benutzer nicht bereits darin enthalten ist.

Gleiches gilt für den umgekehrten Fall oder das „Entfernen“ des „Gefällt mir“:

db.photos.update(
    { 
        "_id": ObjectId("54bb201aa3a0f26f885be2a3"), 
        "likes": ObjectId("54bb2244a3a0f26f885be2a4")
    },
    {
        "$inc": { "likeCount": -1 },
        "$pull": { "likes": ObjectId("54bb2244a3a0f26f885be2a4") }
    }
)

Das Wichtigste hier ist, dass die Abfragebedingungen verwendet werden, um sicherzustellen, dass kein Dokument berührt wird, wenn nicht alle Bedingungen erfüllt sind. Die Zählung erhöht sich also nicht, wenn der Benutzer bereits abgestimmt hat, oder verringert sich, wenn seine Stimme zum Zeitpunkt der Aktualisierung nicht mehr vorhanden war.

Natürlich ist es nicht praktikabel, ein Array mit ein paar hundert Einträgen in einem Dokument in einem anderen Teil Ihrer Anwendung wieder einzulesen. Aber MongoDB hat auch eine sehr standardisierte Methode, um damit umzugehen:

db.photos.find(
    { 
        "_id": ObjectId("54bb201aa3a0f26f885be2a3"), 
    },
    { 
       "photo": 1
       "likeCount": 1,
       "likes": { 
          "$elemMatch": { "$eq": ObjectId("54bb2244a3a0f26f885be2a4") }
       }
    }
)

Diese Verwendung von $elemMatch in der Projektion gibt nur den aktuellen Benutzer zurück, wenn er vorhanden ist, oder nur ein leeres Array, wo er nicht vorhanden ist. Dadurch kann der Rest Ihrer Anwendungslogik erkennen, ob der aktuelle Benutzer bereits eine Stimme abgegeben hat oder nicht.

Das ist die grundlegende Technik und kann für Sie so funktionieren, aber Sie sollten sich darüber im Klaren sein, dass eingebettete Arrays nicht unendlich erweitert werden sollten und dass es auch eine feste 16-MB-Grenze für BSON-Dokumente gibt. Das Konzept ist also solide, kann aber nicht alleine verwendet werden, wenn Sie Tausende von „Gefällt mir“-Stimmen für Ihren Inhalt erwarten. Es gibt ein Konzept, das als "Bucketing" bekannt ist und in diesem Beispiel für das Design von Hybridschemas ausführlich erörtert wird, das es einer Lösung ermöglicht, eine große Menge an "Likes" zu speichern. Sie können sich das zusammen mit den grundlegenden Konzepten hier ansehen, um dies in großem Umfang zu tun.