2010-04-11 13 views
10

Tengo un sistema donde los usuarios registrados pueden votar/votar por los comentarios de una imagen. Es muy similar al sistema de votación de Stack Overflow.Recuperación efectiva para un sistema de votación en PHP y MySQL

que almacenar los votos en una tabla con valores como tal:

vote_id | vote_comment_id | vote_user_id | vote_date | vote_type 

Ahora tengo algunas preguntas acerca de la velocidad y la eficiencia de los siguientes:

PROBLEMA: Una vez que un usuario abre la página de la imagen con comentarios, necesito si ese usuario ya ha votado ARRIBA/ABAJO en un comentario para mostrarlo; "votó a favor" o "votó negativo" al lado del comentario (en Stack Overflow, la imagen del voto está resaltada).

MI POSIBLE SOLUCIÓN: Ahora cuando abro un bucle I Página de imágenes a través de cada comentario, y el bucle de I a mi mesa de votos, así y comprobar si un usuario ha votado y mostrar el estado (que comparan la vote_user_id con la sesión del usuario).

¿Qué tan eficiente es esto? ¿Alguien tiene un mejor enfoque para abordar este tipo de problema?

+0

¿Cómo está almacenando si se trata de un voto positivo o negativo? –

+0

Bueno, lo perdí para ponerlo aquí. Tengo un campo 'vote_type' en mi tabla – Adnan

Respuesta

2

se recorre la tabla de votos? ¿Estás leyendo toda la base de datos en la memoria y luego recorriéndola?

¿Ha intentado consultar la base de datos solo para los datos relevantes?

SELECT vote_comment_id, vote_type 
FROM vote 
WHERE vote_user_id = 34513 
    AND vote_comment_id IN (3443145, 3443256, 3443983) 
+0

3.4+ millones de comentarios. ¡Sitio activo que tienes allí! :) – Atli

2

no mencionas qué base de datos estás usando pero supongo que alguna variante de SQL.

así, en lugar de bucle a través de toda la tabla de votos, se puede hacer algo como

select vote_type from vote_table where vote_comment_id = $commentId and vote_user_id = $userId 

o mejor aún, cuando se está recuperando los comentarios reales que puede hacer un left join al igual que

select c.*, v.vote_type from comments c left join (select * from votes where vote_user_id = $userId) v on v.vote_comment_id = c.comment_id 

luego verifique si vote_type es nulo, hacia arriba o hacia abajo en su ciclo de visualización. esto podría ser menos eficiente si tiene 1000 comentarios y solo muestra 10 a la vez, en cuyo caso el primer método debería ayudar.

[editado después de comentario anterior sobre la columna vote_type]

+0

Uso MySQL, y lo siento por olvidarlo Tengo un vote_type. Voy a probar tu solución ahora mismo. – Adnan

0

¿No necesitaría una columna para lo que haya votado el usuario, es decir, post_id?

Puede hacer una consulta de selección, ver si existe una fila para la publicación y el usuario actuales: si se devuelve una fila, han votado.


En realidad, acabo de notar que vote_comment_id no es lo que he leído como (vote_comment).

sólo tiene que comprobar si existe una fila

-1

Mi solución es a buscar votos de todos los usuarios cuando ha de iniciar sesión en una sesión. Fetch identificadores de todos los comentarios en dos matrices:

$_SESSION['votes'] = array(
    'up' => array(12, 854, 87, 78), 
    'down' => array(84, 32, 77) 
); 

y cuando el acceso del usuario algún tipo de control página si existe su id en cualquiera de esas matrices.

+4

Eso es una pérdida de recursos increíble. Básicamente está buscando y almacenando una montaña de datos que, con toda probabilidad, nunca se utilizarán. - Los datos ya están almacenados dentro de MySQL, y es mucho más eficiente que MySQL busque cada voto cuando sea necesario, que buscarlos todos al iniciar sesión y almacenarlos en la sesión (esencialmente duplicándolos) donde serán cargados en PHP. en cada solicitud. – Atli

1

Trate de evitar el uso de subselect especialmente si está recuperando gran cantidad de filas.

select c.*, v.vote_type 
from comments c 
left join vote v 
on v.vote_comment_id = c.comment_id 
and v.vote_user_id = $userId 

Usando la instrucción CASE para mostrar/ocultar vote_type.

select c.*, CASE v.vote_user_id WHEN $userId 
THEN v.vote_type /*compare vote_user_id with the user's session*/ 
ELSE null END AS 'votetype' /*hide vote_type */ 
from comments c 
left join vote v 
on v.vote_comment_id = c.comment_id 
0

Tengo un sitio con una lógica similar. No rastreo los votos individuales (para esto), solo tengo una tabla de publicaciones (imágenes), con un conteo de votos y un campo de texto con ID de usuario: voto; ID de usuario: voto ... pares, donde el voto es +/-. De esta forma, no necesito seleccionar de la tabla de enormes votos y necesito cargar la fila que pertenece a la publicación de todos modos. Una simple búsqueda de cadenas para "ID de usuario:" revelará si el usuario actual votó o no.

Las transacciones ACID son necesarias para mantener el conteo de votos y el campo de texto de los votos consistentes.

Cuestiones relacionadas