sql >> Database >  >> NoSQL >> MongoDB

Invoegen indien niet bestaat, anders MongoDB verwijderen

Dat is geen goede manier om up-votes en downvotes te implementeren. Afgezien van het feit dat het aggregatieraamwerk op geen enkele manier een mechanisme is om documenten bij te werken, lijkt u te zijn aangetrokken tot de gedachte dat het een oplossing kan zijn vanwege de logica die u wilt implementeren. Maar aggregaat wordt niet bijgewerkt.

Wat je wilt op je, laten we het een "vraag"-schema noemen, is een structuur als deze:

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

Dat is iets dat goed kan werken met atomaire updates en je tegelijkertijd wat stateful informatie over het object kan geven.

Voor de arrays "upvoted" en "downvoted" gaan we ervan uit dat de stemmen van de "gebruikers" een vergelijkbare unieke ObjectId-waarde hebben. Dus wat we gaan doen is $push of $pull van beide arrays en ook "verhoog/verlaag" de tellerwaarden samen met elk van die bewerkingen.

Zo werkt dit voor een upvote:

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 },
    }
)

Eigenlijk zijn dat twee bewerkingen die je zou kunnen doen met de Bulk operations AP Ik ook (waarschijnlijk de beste manier eigenlijk) maar het heeft een punt. De eerste instructie komt alleen overeen met een document waarin de huidige gebruiker een "downvote" heeft geregistreerd in de array. Zoals het is, hebben we die gebruikers-ID-waarde al "geduwd" naar de "downvotes" -array. Als het er niet is, wordt er geen update uitgevoerd. Maar u pusht en trekt beide uit de respectieve arrays en tegelijkertijd "verhoogt/verlaagt" u de tellervelden.

Met de tweede verklaring die alleen overeenkomt met iets waar de eerste dat niet deed, maak je een eerlijke beoordeling dat je nu geen "downvotes" hoeft aan te raken en alleen de upvote-velden hoeft te verwerken. In beide gevallen is het veilig om ervoor te zorgen dat de belangrijkste voorwaarde is dat de huidige gebruikers-ID-waarde niet aanwezig is in de "upvoted" -array.

Voor downvotes zijn de velden gewoon omgekeerd:

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 },
    }
)

Natuurlijk kunt u de logische voortgang zien naar het eenvoudig annuleren van elke "upvote/downvote" voor de gebruiker in kwestie. U kunt er ook slim mee omgaan als u wilt en de informatie in uw client blootleggen om niet alleen te laten zien of de huidige gebruiker al "upvoted/downvoted" heeft, maar ook om klikacties te beheren en onnodige verzoeken te elimineren.




  1. Meerdere indexen tegelijk bouwen

  2. Valideer object tegen Mongoose-schema zonder op te slaan als een nieuw document

  3. Mongoengine creation_time attribuut in Document

  4. Kreeg dubbele gegevens wanneer u zich meerdere keren abonneert