MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

Insira se não existir, senão remova o MongoDB


Essa não é uma boa maneira de implementar votos positivos e negativos. Além do framework de agregação não ser um mecanismo para atualizar documentos de forma alguma, você parece ter gravitado para pensar que pode ser uma solução devido à lógica que você deseja implementar. Mas o agregado não atualiza.

O que você quer no seu, bem, vamos chamá-lo de esquema de "pergunta" é uma estrutura como esta:
{
    "_id": ObjectId("53f51a844ffa9b02cf01c074"),
    "upvoted": [],
    "downvoted": [],
    "upvoteCount": 0,
    "downvoteCount": 0
}

Isso é algo que pode funcionar bem com atualizações atômicas e realmente fornecer algumas informações de estado sobre o objeto ao mesmo tempo.

Para os arrays "upvoted" e "downvoted", vamos considerar que a votação dos "users" tem um valor de ObjectId exclusivo semelhante. Então o que vamos fazer é $push ou $pull de qualquer matriz e também "incrementar/diminuir" os valores do contador junto com cada uma dessas operações.

Veja como isso funciona para um 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 },
    }
)

Na verdade, são duas operações, que você pode fazer com o AP de operações em massa Eu também (provavelmente a melhor maneira), mas tem um ponto nisso. A primeira instrução corresponderá apenas a um documento em que o usuário atual tenha um "downvote" registrado na matriz. Como isso, já "enviamos" esse valor de ID do usuário para o array "downvotes". Se não estiver lá, nenhuma atualização é feita. Mas você empurra e puxa dos respectivos arrays e também "incrementa/decrementa" os campos do contador ao mesmo tempo.

Com a segunda declaração, que corresponderá apenas a algo onde a primeira não corresponde, você faz uma avaliação justa de que agora não precisa tocar em "downvotes" e apenas lidar com os campos de upvote. Em ambos os casos, a coisa segura a fazer é certificar-se de que a condição principal é que o valor atual do ID do usuário não esteja presente no array "upvoted".

Para downvotes, os campos são apenas invertidos:
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 },
    }
)

Naturalmente você pode ver a progressão lógica para simplesmente cancelar qualquer "upvote/downvote" para o usuário em questão. Além disso, você pode ser esperto sobre isso se quiser e expor as informações em seu cliente para não apenas mostrar se o usuário atual já "votou positivo/desaprovado", mas também controlar as ações de clique e eliminar solicitações desnecessárias.