2010-03-29 8 views
6

Attualmente sto sviluppando un'applicazione per consentire agli studenti di gestire i loro corsi e non so davvero come progettare il database per una funzione specifica. Il cliente desidera, molto simile a Facebook, che quando uno studente visualizza l'elenco di persone attualmente in un corso specifico, vengono visualizzate per prime le persone con i corsi più comuni con l'utente connesso. Quasi uguale alla funzione Facebook "Suggerimenti amici" con un filtro aggiuntivo.Chiedendosi come funziona Facebook "Mutual friends"

Come funzionalità aggiuntiva, vorrei aggiungere una funzione di ricerca per consentire agli studenti di cercarne un'altra e visualizzare per primi nei risultati di ricerca le persone con i corsi più comuni con l'utente che ha effettuato l'accesso.

Attualmente utilizzo MySQL, ho intenzione di utilizzare Cassandra per alcune altre funzionalità e utilizzo Memcached per la cache dei risultati e Sphinx per la ricerca.

Grazie.

-

L'applicazione è sviluppata in Python, BTW

E ho dimenticato di dire che l'approccio standard (con un bel query MySQL per calcolare tutto questo con una clausola ORDER BY) è troppo wayyyys lento. Quindi, dato che le letture sono molto più frequenti delle letture, vorrei che la maggior parte della logica avvenga una volta, quando viene aggiunto il rapporto persone < -> corso.

Ho pensato di aggiornare un contatore "corsi comuni" specifico per una tupla (utente, corso) che verrà aumentato per tutti gli utenti di un corso quando l'utente connesso si unisce a un nuovo corso (o diminuisce quando lo lascia) .

+0

Cosa intendi per le persone con i più amici comuni?Vuoi dire di trovare un altro utente che ha tanti degli stessi amici della persona che è attualmente loggata? dovrai anche dire in quale lingua ti stai sviluppando. Sembra roba basata sul web, ma mySQL può essere usato per applicazioni standalone. E abbiamo ancora bisogno di sapere se è PHP/ASP/JS o qualche altra lingua. – thecoshman

+0

Sì, mi hai capito bene. L'applicazione è sviluppata in Python, ma in realtà, mi troverei ad affrontare lo stesso identico problema con qualsiasi altra lingua. Non mi aspetto che le persone mi aiutino con il codice, ma con idee strutturali :) – Pierre

+0

L'implementazione di "amici comuni" sarebbe in qualche modo diversa dall'implementazione di una funzione "più reciproci corsi". Il primo ha bisogno solo di un tipo di entità (persona) e una relazione "è amico di". Quest'ultimo aveva due entità (studente, corso) e relazione tra studente e corso da cui le relazioni tra gli studenti avrebbero bisogno di essere estrapolate. –

risposta

4

Se hai già la soluzione, ma il problema è solo la velocità di tale query, provare a farlo prima. Quando le amicizie di un utente cambiano, riesegui un lavoro che calcola queste cose e memorizza tutti i risultati. Non razionare il suo come risultato di una richiesta, quando hai bisogno del risultato così rapidamente. Fai cose così costose solo una volta e fallo prima che una richiesta venga mai fatta.

+0

Quindi, quando viene aggiunta una nuova relazione, fai ciò che ho pensato: aggiorna un contatore per le relazioni reciproche (in Cassandra) per ogni utente già nel corso. Quando si visualizzano i risultati, basta prendere i dati da Cassandra, visualizzare i risultati come vengono (già ordinati) e visualizzare altri utenti (senza relazioni) dopo ... - La mia unica preoccupazione sarebbe comunque la prestazione. Non sarebbe un enorme sovraccarico quando si unirà a un corso con migliaia di persone al suo interno? – Pierre

+0

Dipende se si esegue "per x in y: updatesql (nuovo valore)" o "UPDATE contatore = contatore + 1 dove ...". Il primo sta andando a colpire la rete in testa. Il secondo dovrebbe essere piuttosto veloce. –

+0

Sì. Se fatto in SQL, sono totalmente d'accordo con te. Ma il problema delle prestazioni è ancora (un po ') vivo. Se parlo di un corso con 100.000 persone (sì, c'è!), La query non 'SELECT u.id Dagli utenti u le relazioni JOIN INTERNO r ON (u.id == r.user_id_1 O u.id == r.user_id_2) ORDINA DI r.mutual_counter LIMIT ... 'essere un po 'caro? Se uso Cassandra, posso memorizzare i dati già ordinati.Ma per quanto ne so, devo scorrere le relazioni manualmente:/ – Pierre

4

Supponiamo di avere una tabella denominata Users e la chiave primaria è UserID. Quindi hai un tavolo chiamato Friends con 2 colonne chiamate UserID (PK) e FriendUserID.

Diciamo che avete 2 utenti, 20 e 50.

Quando 20 aggiunge 50 come amico, l'applicazione aggiunge una nuova riga:

INSERT INTO `Friends` (`UserID`, `FriendUserID`) VALUES (20, 50) 

e quando il 50 conferma l'amicizia, si aggiunge un'altra riga con I valori passati:

INSERT INTO `Friends` (`UserID`, `FriendUserID`) VALUES (50, 20) 

Quando si vuole trovare amici comuni tra 20 e 50, è sufficiente:

SELECT `UserID` FROM `Friends` AS `A`, `Friends` AS B WHERE `A`.`FriendUserID` = 20 AND `A`.`UserID` = `B`.`UserID` AND `B`.`FriendUserID` = 50 
+0

Oh sì grazie. Che funzioni. Ma questa non è sicuramente una soluzione praticabile, per problemi di prestazioni. Anche se tale richiesta viene effettuata quando si verifica una nuova relazione per calcolare e memorizzare i risultati, questo sarebbe troppo lento con una tabella abbastanza grande. – Pierre

+0

Questo sembra buono, ma perché non trovi i reciproci amici e li memorizzi in un'altra tabella in modo che tu non debba fare i calcoli ancora e ancora, invece esegui un lavoro che aggiornerebbe i reciproci amici ogni volta che l'utente crea una nuova connessione – Magesh

0

vorrei spezzare questo come (2) le domande e trovare l'intersezione in Python:

#Query 1 - Get the user's friends 
SELECT friend_id FROM friends WHERE user_id = 'my user id' 

#Query 2 - Get the users enrolled in the course 
SELECT student_id FROM course_enrollment WHERE course_id = 'course id' 

poi trovare l'intersezione in Python. Quindi puoi lasciare che il database faccia il caching, ecc. Senza alcun join per rallentare le cose.

Problemi correlati