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

Esquema para classificações de usuários - banco de dados de chave/valor


Em primeiro lugar, 'Dicionário em Classe de Usuário' não é uma boa ideia. porque? Adicionar um objeto de taxa extra requer o envio de um novo item para a matriz, o que implica que o item antigo será removido, e essa inserção é chamada de "mover um documento ". A movimentação de documentos é lenta e o MongoDB não é tão bom em reutilizar o espaço vazio, portanto, mover muitos documentos pode resultar em grandes quantidades de arquivos de dados vazios (algum texto no livro 'MongoDB The Definitive Guide').

Então, qual é a solução correta:suponha que você tenha uma coleção chamada Blogs e queira implementar uma solução de classificação para suas postagens de blog e, além disso, acompanhe cada operação de taxa baseada no usuário.

O esquema para um documento de blog seria assim:
{
   _id : ....,
   title: ....,
   ....
   rateCount : 0,
   rateValue : 0,
   rateAverage: 0
}

Você precisa de outra coleção (Taxas) com este esquema de documento:
{
    _id: ....,
    userId: ....,
    postId:....,
    value: ..., //1 to 5
    date:....   
}

E você precisa definir um índice adequado para isso:

db.Rates.ensureIndex({userId : 1, postId : 1})// very useful. it will result in a much faster search operation in case you want to check if a user has rated the post previously

Quando um usuário deseja avaliar, primeiro você precisa verificar se o usuário avaliou a postagem ou não. suponha que o usuário seja 'user1' , a consulta então seria
var ratedBefore = db.Rates.find({userId : 'user1', postId : 'post1'}).count()

E com base em ratedBefore , se !ratedBefore em seguida, insira um novo documento de taxa na coleção de Taxas e atualize o status do blog, caso contrário, o usuário não terá permissão para classificar
if(!ratedBefore)
{
    var postId = 'post1'; // this id sould be passed before by client driver
    var userId = 'user1'; // this id sould be passed before by client driver
    var rateValue = 1; // to 5
    var rate = 
    {       
       userId: userId,
       postId: postId,
       value: rateValue,
       date:new Date()  
    };

    db.Rates.insert(rate);
    db.Blog.update({"_id" : postId}, {$inc : {'rateCount' : 1, 'rateValue' : rateValue}});
}

Então o que vai acontecer com rateAverage ?Recomendo calculá-lo com base em rateCount e rateValue no lado do cliente, é fácil atualizar rateAverage com mongoquery , mas você não deve fazê-lo. porque? A resposta simples é:este é um trabalho muito fácil para o cliente lidar com esse tipo de trabalho e colocar a média em cada documento do blog precisa de uma operação de atualização desnecessária.

a consulta média seria calculada como:
var blog = db.Blog.findOne({"_id" : "post1"});
var avg = blog.rateValue / blog.rateCount;
print(avg);

Com essa abordagem, você obterá o máximo desempenho com o mongodb e acompanhará todas as taxas com base no usuário, postagem e data.