sql >> Databáze >  >> NoSQL >> MongoDB

Jak modelovat systém hlasování Líbí se pomocí MongoDB

Bez ohledu na to, jak strukturujete svůj celkový dokument, potřebujete v zásadě dvě věci. To je v podstatě vlastnost pro "počet" a "seznam" těch, kteří již zveřejnili své "lajky", aby se zajistilo, že nebudou odeslány žádné duplikáty. Zde je základní struktura:

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

V každém případě existuje jedinečné „_id“ pro váš „příspěvek s fotografií“ a jakékoli informace, které chcete, ale pak další pole, jak je uvedeno. Vlastností „likes“ je zde pole, které bude obsahovat jedinečné hodnoty „_id“ z objektů „user“ ve vašem systému. Takže každý "uživatel" má někde svůj jedinečný identifikátor, buď v místním úložišti nebo OpenId nebo tak něco, ale jedinečný identifikátor. Zůstanu u ObjectId pro příklad.

Když někdo odešle "To se mi líbí" příspěvku, chcete vydat následující prohlášení o aktualizaci:

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

Nyní $inc operace tam zvýší hodnotu "likeCount" o zadané číslo, takže zvyšte o 1. $push operace přidá jedinečný identifikátor uživatele do pole v dokumentu pro budoucí použití.

Zde je důležité především vést záznam o těch uživatelích, kteří hlasovali, a o tom, co se děje v části prohlášení „dotaz“. Kromě výběru dokumentu k aktualizaci pomocí jeho vlastního jedinečného „_id“ je další důležitou věcí zkontrolovat pole „líbí se mi“, abyste se ujistili, že aktuální hlasující uživatel tam již není.

Totéž platí pro opačný případ nebo „odstranění“ „like“:

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

Hlavní důležitou věcí jsou zde použité podmínky dotazu, aby se zajistilo, že se žádný dokument nedotkne, pokud nejsou splněny všechny podmínky. Počet se tedy nezvýší, pokud uživatel již hlasoval, ani se nesníží, pokud jeho hlas v době aktualizace již nebyl přítomen.

Samozřejmě není praktické číst pole s několika stovkami položek v dokumentu zpět v jakékoli jiné části vaší aplikace. Ale MongoDB má také velmi standardní způsob, jak to zvládnout:

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

Toto použití $elemMatch v projekci vrátí aktuálního uživatele pouze v případě, že je přítomen, nebo pouze prázdné pole tam, kde nejsou. To umožňuje zbytku vaší aplikační logiky vědět, zda aktuální uživatel již hlasoval nebo ne.

To je základní technika a může vám fungovat tak, jak je, ale měli byste si být vědomi toho, že embedded pole by neměla být rozšiřována donekonečna a existuje také pevný limit 16 MB pro dokumenty BSON. Koncept je tedy dobrý, ale nelze jej použít samostatně, pokud u svého obsahu očekáváte 1000 „like-hlasů“. Existuje koncept známý jako „bucketing“, který je podrobně popsán v tomto příkladu návrhu Hybrid Schema, který umožňuje jedno řešení pro ukládání velkého množství „lajků“. Můžete se na to podívat, abyste to mohli použít spolu se základními pojmy zde, jako způsob, jak toho dosáhnout ve velkém.




  1. Mongoose populace vložená

  2. Schéma Mongoose nebylo pro model zaregistrováno

  3. Přístup k MongoDB z Go

  4. Node.js a Mongoose regex dotaz na více polí