sql >> Databasteknik >  >> NoSQL >> MongoDB

Infoga om det inte finns, annars ta bort MongoDB

Det är inte ett bra sätt att genomföra upp- och nedröster. Bortsett från att aggregeringsramverket inte är en mekanism för att uppdatera dokument på något sätt, verkar du ha dragit till att tro att det kan vara en lösning på grund av den logik du vill implementera. Men aggregat uppdateras inte.

Vad du vill ha på ditt, ja låt oss kalla det ett "frågeschema" är en struktur så här:

{
    "_id": ObjectId("53f51a844ffa9b02cf01c074"),
    "upvoted": [],
    "downvoted": [],
    "upvoteCount": 0,
    "downvoteCount": 0
}

Det är något som kan fungera bra med atomuppdateringar och som faktiskt ger dig lite tillståndsfull information om objektet på samma gång.

För arrayerna "upvoted" och "downvoted" kommer vi att överväga att "användarnas" röstning har ett liknande unikt ObjectId-värde. Så vad vi ska göra är $push eller $pull från endera matrisen och även "öka/minska" räknarvärdena tillsammans med var och en av dessa operationer.

Så här fungerar det för en uppröstning:

db.questions.update(
    { 
        "_id": ObjectId("53f51a844ffa9b02cf01c074"),
        "upvoted": { "$ne": ObjectId("53f51c0a4ffa9b02cf01c075") }
        "downvoted": ObjectId("53f51c0a4ffa9b02cf01c075")
    },
    {         
        "$push": { "upvoted": ObjectId("53f51c0a4ffa9b02cf01c075") },
        "$inc": { "upvoteCount": 1, "downvoteCount": -1 },
        "$pull": { "downvoted": ObjectId("53f51c0a4ffa9b02cf01c075") },
    }
)

db.questions.update(
    { 
        "_id": ObjectId("53f51a844ffa9b02cf01c074"),
        "upvoted": { "$ne": ObjectId("53f51c0a4ffa9b02cf01c075") }
    },
    {
        "$push": { "upvoted": ObjectId("53f51c0a4ffa9b02cf01c075") },
        "$inc": { "upvoteCount": 1 },
    }
)

Det är faktiskt två operationer, som du kan göra med Bulk operations AP Jag också (förmodligen det bästa sättet egentligen) men det har en poäng med det. Den första satsen kommer bara att matcha ett dokument där den nuvarande användaren har en "nedröst" inspelad i arrayen. Som det är, har vi redan "skjutit" det användar-id-värdet till "downvotes"-arrayen. Om den inte finns där görs ingen uppdatering. Men du både trycker och drar från respektive arrayer och "ökar/minskar" även räknarfälten samtidigt.

Med det andra påståendet som bara kommer att matcha något där det första inte gjorde det, gör du en rättvis bedömning att nu behöver du inte röra "downvotes" och bara hantera upvote-fälten. I båda fallen är det säkra att se till att huvudvillkoret är att det aktuella användar-id-värdet inte finns i arrayen "upvoted".

För nedröster är fälten bara omvända:

db.questions.update(
    { 
        "_id": ObjectId("53f51a844ffa9b02cf01c074"),
        "downvoted": { "$ne": ObjectId("53f51c0a4ffa9b02cf01c075") }
        "upvoted": ObjectId("53f51c0a4ffa9b02cf01c075")
    },
    {         
        "$pull": { "upvoted": ObjectId("53f51c0a4ffa9b02cf01c075") },
        "$inc": { "upvoteCount": -1, "downvoteCount": 1 },
        "$push": { "downvoted": ObjectId("53f51c0a4ffa9b02cf01c075") },
    }
)

db.questions.update(
    { 
        "_id": ObjectId("53f51a844ffa9b02cf01c074"),
        "downvoted": { "$ne": ObjectId("53f51c0a4ffa9b02cf01c075") }
    },
    {
        "$push": { "downvoted": ObjectId("53f51c0a4ffa9b02cf01c075") },
        "$inc": { "downvoteCount": 1 },
    }
)

Naturligtvis kan du se den logiska utvecklingen att helt enkelt avbryta valfri "uppröstning/nedröstning" för användaren i fråga. Du kan också vara smart med det om du vill och exponera informationen i din klient för att inte bara visa om den nuvarande användaren redan har "röstat upp/ned" utan också kontrollerar klickåtgärder och eliminerar onödiga förfrågningar.




  1. mgo time.Time eller boolesk check

  2. Mongodb lägger till ett nytt fält i ett befintligt dokument, med specifik position

  3. Uppdatera ett underdokument i mongodb?

  4. Spara en HASH till Redis på en rails-app