sql >> Base de Datos >  >> NoSQL >> MongoDB

Esquema para calificaciones de usuarios:base de datos clave/valor

En primer lugar, 'Dictionary in User Class' no es una buena idea. ¿por qué? Agregar un objeto de tarifa adicional requiere insertar un nuevo elemento en la matriz, lo que implica que se eliminará el elemento anterior, y esta inserción se denomina "mover un documento ". Mover documentos es lento y MongoDB no es tan bueno en la reutilización del espacio vacío, por lo que mover mucho los documentos puede resultar en grandes franjas de archivos de datos vacíos (algo de texto en el libro 'MongoDB The Definitive Guide').

Entonces, ¿cuál es la solución correcta? Suponga que tiene una colección llamada Blogs y desea implementar una solución de calificación para las publicaciones de su blog y, además, realizar un seguimiento de cada operación de calificación basada en el usuario.

El esquema para un documento de blog sería como:

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

Necesita otra colección (Tarifas) con este esquema de documento:

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

Y necesita definir un índice adecuado para ello:

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

Cuando un usuario quiere calificar, primero debe verificar si el usuario ha calificado la publicación o no. suponga que el usuario es 'user1' , la consulta sería

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

Y basado en ratedBefore , si !ratedBefore luego inserte un nuevo documento de tarifas en la colección de tarifas y actualice el estado del blog; de lo contrario, el usuario no puede calificar

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

Entonces, ¿qué va a pasar con rateAverage? ?Recomiendo encarecidamente calcularlo en función de rateCount y rateValue en el lado del cliente, es fácil actualizar rateAverage con mongoquery , pero no deberías hacerlo. ¿por qué? La respuesta simple es:este es un trabajo muy fácil para que el cliente maneje este tipo de trabajos y poner un promedio en cada documento del blog necesita una operación de actualización innecesaria.

la consulta promedio se calcularía como:

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

Con este enfoque, obtendrá el máximo rendimiento con mongodb y tendrá un seguimiento de cada tarifa según el usuario, la publicación y la fecha.