Come modellare un sistema di voto “Mi piace” con MongoDB

Attualmente sto lavorando su un’app mobile. Fondamentalmente le persone possono pubblicare le loro foto e ai follower possono piacere le foto come Instagram. Io uso mongodb come database. Come instagram, potrebbero esserci molti Mi piace per una singola foto. Quindi usare un documento per un singolo “mi piace” con l’indice non sembra ragionevole perché sprecherà molta memoria. Tuttavia, mi piacerebbe che un utente aggiungesse un mi piace velocemente. Quindi la mia domanda è come modellare il “mi piace”? Fondamentalmente il modello dati è molto simile a instagram ma usa Mongodb.

Non importa quanto strutturi il tuo documento generale, ci sono fondamentalmente due cose che ti servono. Questa è fondamentalmente una proprietà quattro un “conteggio” e una “lista” di coloro che hanno già pubblicato lì “mi piace” al fine di garantire che non ci siano duplicati inviati. Ecco una struttura di base:

 { "_id": ObjectId("54bb201aa3a0f26f885be2a3") "photo": "imagename.png", "likeCount": 0 "likes": [] } 

In ogni caso, c’è un “_id” unico per il tuo “post fotografico” e qualsiasi informazione tu voglia, ma poi gli altri campi come menzionato. La proprietà “mi piace” qui è un array, e che manterrà i valori unici “_id” dagli oggetti “utente” nel tuo sistema. Quindi ogni “utente” ha il proprio identificatore univoco da qualche parte, nella memoria locale o OpenId o qualcosa del genere, ma un identificatore univoco. ObjectId con ObjectId per l’esempio.

Quando qualcuno invia un “mi piace” a un post, desideri emettere la seguente dichiarazione di aggiornamento:

 db.photos.update( { "_id": ObjectId("54bb201aa3a0f26f885be2a3"), "likes": { "$ne": ObjectId("54bb2244a3a0f26f885be2a4") } }, { "$inc": { "likeCount": 1 }, "$push": { "likes": ObjectId("54bb2244a3a0f26f885be2a4") } } ) 

Ora l’operazione $inc aumenterà il valore di “likeCount” per il numero specificato, quindi aumenta di 1. L’operazione $push aggiunge l’identificativo univoco per l’utente alla matrice nel documento per riferimento futuro.

La cosa più importante qui è tenere un registro degli utenti che hanno votato e di ciò che sta accadendo nella parte “query” dell’istruzione. Oltre alla selezione del documento da aggiornare tramite il proprio “_id”, l’altra cosa importante è controllare che l’array “Mi piace” assicuri che l’utente che ha votato attualmente non sia già lì.

Lo stesso vale per il caso inverso o “rimozione” del “mi piace”:

 db.photos.update( { "_id": ObjectId("54bb201aa3a0f26f885be2a3"), "likes": ObjectId("54bb2244a3a0f26f885be2a4") }, { "$inc": { "likeCount": -1 }, "$pull": { "likes": ObjectId("54bb2244a3a0f26f885be2a4") } } ) 

La cosa più importante qui è la condizione di query utilizzata per assicurarsi che nessun documento venga toccato se tutte le condizioni non sono soddisfatte. Quindi il conteggio non aumenta se l’utente avesse già votato o diminuito se il suo voto non fosse più presente al momento dell’aggiornamento.

Naturalmente non è pratico leggere un array con un paio di centinaia di voci in un documento in qualsiasi altra parte della vostra applicazione. Ma MongoDB ha un modo molto standard per gestire anche questo:

 db.photos.find( { "_id": ObjectId("54bb201aa3a0f26f885be2a3"), }, { "photo": 1 "likeCount": 1, "likes": { "$elemMatch": { "$eq": ObjectId("54bb2244a3a0f26f885be2a4") } } } ) 

Questo uso di $elemMatch in proiezione restituirà l’utente corrente solo se presente o solo un array vuoto dove non lo sono. Ciò consente al resto della logica dell’applicazione di essere a conoscenza se l’utente corrente ha già inserito un voto o meno.

Questa è la tecnica di base e potrebbe funzionare per te così com’è, ma dovresti sapere che gli array incorporati non dovrebbero essere infinitamente estesi, e c’è anche un limite di 16 MB sui documenti BSON. Quindi il concetto è valido, ma non può essere usato da solo se ci si aspetta 1000 di “voti simili” sul tuo contenuto. Esiste un concetto noto come “bucketing” che è discusso in dettaglio in questo esempio per la progettazione dello schema ibrido che consente a una soluzione di memorizzare un volume elevato di “mi piace”. Puoi guardare a questo da usare insieme ai concetti di base qui come un modo per farlo a volume.