MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

Schéma pour les évaluations des utilisateurs - DB clé/valeur

Tout d'abord, 'Dictionary in User Class' n'est pas une bonne idée. Pourquoi? L'ajout d'un objet de taux supplémentaire nécessite de pousser un nouvel élément dans le tableau, ce qui implique que l'ancien élément sera supprimé, et cette insertion est appelée "déplacer un document ". Le déplacement de documents est lent et MongoDB n'est pas si doué pour réutiliser l'espace vide, donc déplacer beaucoup de documents peut entraîner de grandes quantités de fichiers de données vides (certains textes dans le livre 'MongoDB The Definitive Guide').

Alors quelle est la bonne solution :supposons que vous ayez une collection nommée Blogs et que vous souhaitiez implémenter une solution de notation pour vos articles de blog, et en plus garder une trace de chaque opération de tarification basée sur l'utilisateur.

Le schéma d'un document de blog ressemblerait à :

{
   _id : ....,
   title: ....,
   ....
   rateCount : 0,
   rateValue : 0,
   rateAverage: 0
}

Vous avez besoin d'une autre collection (Tarifs) avec ce schéma de document :

{
    _id: ....,
    userId: ....,
    postId:....,
    value: ..., //1 to 5
    date:....   
}

Et vous devez définir un index approprié pour cela :

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

Lorsqu'un utilisateur souhaite évaluer, vous devez d'abord vérifier s'il a évalué le message ou non. supposons que l'utilisateur est 'user1' , la requête serait alors

var ratedBefore = db.Rates.find({userId : 'user1', postId : 'post1'}).count()

Et basé sur ratedBefore , si !ratedBefore puis insérez un nouveau document de taux dans la collection Rates et mettez à jour le statut du blog, sinon, l'utilisateur n'est pas autorisé à évaluer

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

Alors que va-t-il arriver à rateAverage ?Je recommande fortement de le calculer en fonction de rateCount et rateValue côté client, il est facile de mettre à jour rateAverage avec mongoquery , mais vous ne devriez pas le faire. Pourquoi? La réponse simple est la suivante :il est très facile pour le client de gérer ce type de travaux et de mettre une moyenne sur chaque document de blog nécessite une opération de mise à jour inutile.

la requête moyenne serait calculée comme suit :

var blog = db.Blog.findOne({"_id" : "post1"});
var avg = blog.rateValue / blog.rateCount;
print(avg);

Avec cette approche, vous obtiendrez des performances maximales avec mongodb et vous aurez une trace de chaque taux en fonction de l'utilisateur, de la publication et de la date.