J’essaie de réaliser exactement ce qui est expliqué ici: Créer un système de messagerie privé comme Facebook et Gmail , mais je ne comprends pas complètement la réponse de Joel Brown. quelqu’un peut-il expliquer s’il vous plaît.
Voici à quoi ressemblent mes tables de firebase database avec des exemples de données (je suppose que je les ai remplies correctement à des fins de démonstration):
J’ai besoin d’afficher une liste de threads basée sur LoginId (le plus récent en haut) à quoi ressemblerait la requête dans LINQ? (ce que je demande est dans un groupe de fils de discussion, donnez-moi le message le plus récent dans chaque fil) – comme si cela se faisait sur facebook.
Je dois afficher TOUS les messages dans un fil de messages (LINQ) -> comme sur Facebook où vous cliquez sur le message et vous verrez toute la “conversation” dans une bande de roulement.
S’il vous plaît aider! Merci
EDIT -> suite Joel, est-ce correct ??
Joel, je suis un peu confus, pouvez-vous s’il vous plaît expliquer (commentaires / questions en gras):
L’idée ici est que chaque fois qu’un utilisateur lance un nouveau thread / message, il commence par un nouvel enregistrement dans la table THREAD. L’utilisateur est alors ajouté en tant que THREAD_PARTICIPANT et le contenu du message est ajouté à MESSAGE qui renvoie au THREAD contenant. Le FK de MESSAGE à USER indique l’auteur du message.
LoginId 1 envoie un message à LoginId2 => le nouvel enregistrement est inséré dans la table MessageThread. Un enregistrement est également inséré dans l’enregistrement MessageThreadParticipant avec MessageThreadId = 1, LoginId = 1 (l’expéditeur). Et un nouvel enregistrement est inséré dans la table des messages avec MessageId = 1, MessageThreadid = 1, SenderLoginId = 1 (correct ??)
c’est ce que j’ai après cette itération:
Je pense que je suis confus car Loginid 2 n’a aucun moyen de savoir qu’il y a un message pour lui. ?? OU peut-être ai-je besoin d’insérer 2 enregistrements dans MessageThreadParticipant? (l’expéditeur et le destinataire) -> De cette façon, les deux peuvent voir toute la “conversation” ??
EDIT2: Joe, je pense que je pourrais faire ça:
SELECT Message.MessageId, Message.CreateDate, Message.Body, Login.Username, Message.SenderLoginId , (SELECT MessageReadState.ReadDate FROM MessageReadState WHERE MessageReadState.MessageId = Message.MessageId ) as ReadDate FROM Message INNER JOIN Login ON Message.SenderLoginId = Login.LoginId INNER JOIN MessageThreadParticipant mtp on mtp.MessageThreadId = Message.MessageThreadId AND ( Message.MessageId in ( SELECT Max(Message.MessageId) FROM MessageThreadParticipant INNER JOIN Message ON MessageThreadParticipant.MessageThreadId = Message.MessageThreadId GROUP BY MessageThreadParticipant.MessageThreadId ) ) Where mtp.LoginId = 2 ORDER BY Message.CreateDate DESC;
Corrigez-moi si j’ai tort, s’il-vous plait 🙂
Eh bien, pourquoi ne pas simplement demander? 🙂
Laissez-moi essayer de cerner ma compréhension de votre exigence. Il me semble que vous regardez un fil de discussion comme une liste linéaire (pas un arbre) de messages entre deux personnes. Je pense que vous voudrez peut-être autoriser plus de personnes en moins de deux. Ce serait comme Facebook dans la mesure où quelqu’un publie un message et que plusieurs personnes peuvent le lire, puis commencer à append des commentaires. Lorsque vous ajoutez un commentaire, il vous place dans le fil de discussion et vous commencez à recevoir des mises à jour de statut et des e-mails vous informant de l’activité du fil, etc. En supposant que ce soit ce que vous recherchez, le schéma que j’ai suggéré à Big Mike n’est pas exactement ce que vous recherchez.
Considérons plutôt ce qui suit:
L’idée ici est que chaque fois qu’un utilisateur lance un nouveau thread / message, il commence par un nouvel enregistrement dans la table THREAD. L’utilisateur est alors ajouté en tant que THREAD_PARTICIPANT et le contenu du message est ajouté à MESSAGE qui renvoie au THREAD contenant. Le FK de MESSAGE à USER indique l’auteur du message.
Lorsqu’un utilisateur lit un message, il reçoit une entrée dans la table MESSAGE_READ_STATE pour indiquer qu’il a marqué le message lu, explicitement ou implicitement, en fonction de la configuration de vos besoins.
Lorsque quelqu’un commente le message initial dans le thread, un second MESSAGE est ajouté avec un FK dans le THREAD d’origine et l’auteur de la réponse (utilisateur) est ajouté à la table THREAD_PARTICIPANT. Et ainsi de suite, les messages sont ajoutés au fil par un, deux ou même plus de participants.
Pour obtenir le message le plus récent dans n’importe quel thread, il suffit de prendre le top 1 de MESSAGE sortingé en ordre décroissant à la date de création (ou une clé d’identité) où le message FK correspond au thread concerné.
Pour obtenir le dernier thread mis à jour pour un utilisateur, obtenez le THREAD lié au top 1 du message sortingé en ordre décroissant à la date de création où le message se trouve dans un thread dans lequel l’utilisateur est THREAD_PARTICIPANT.
J’ai peur de ne jamais pouvoir dire ces choses dans LINQ sans sortir LinqPad. Si vous avez du mal à saisir ma dérive de ce qui précède, je pourrais étoffer la réponse avec des définitions de tableau et du SQL. Il suffit de demander dans les commentaires.
EDIT: Clarification des exigences et mise en œuvre
Clarification des exigences: Au départ, je pensais aux messages publiés publiquement avec la possibilité de commenter, alors que Shane est après la fonction de message direct. Dans ce cas, le destinataire initial doit être inclus dans la table THREAD_PARTICIPANT au début.
Pour plus de clarté, mettons quelques lignes dans les tableaux. Voici le scénario (en l’honneur de la fête du Canada): Utilisateur 1 Utilisateur de la DM 2 à poser à propos de la rencontre pour une bière. L’utilisateur 2 répond par une question sur l’endroit où se rencontrer et les réponses de l’utilisateur 1. Les tableaux ressemblent à ceci: (probablement trop simplifié)
EDIT # 2: Accédez à SQL pour la liste de tous les messages d’un thread, avec un état de lecture …
En utilisant le schéma de @ OP, ce SQL obtiendra une liste de messages dans un thread donné avec une indication indiquant si un utilisateur donné a lu chaque message ou non. Les messages sont dans le premier ordre le plus récent.
SELECT Message.MessageId , Message.CreateDate , Message.Body , Login.Username , (SELECT MessageReadState.ReadDate FROM MessageReadState WHERE MessageReadState.MessageId = Message.MessageId and MessageReadState.LoginId = 2) as ReadState FROM (Message INNER JOIN Login ON Message.SenderLoginId = Login.LoginId) WHERE (((Message.MessageThreadId)=10)) ORDER BY Message.CreateDate DESC;
Notez que l’astuce, s’il est juste de l’appeler ainsi, est que l’état de lecture est capté avec une sous-sélection. Cela est nécessaire car une partie des critères pour obtenir l’état de lecture nécessite une clause where qui ne peut pas être satisfaite avec une jointure externe. Par conséquent, vous utilisez la sous-sélection pour déterminer quelle valeur (éventuellement manquante) vous voulez dans la table enfant MessageReadState.
EDIT 3: SQL pour obtenir tous les threads avec le dernier message dans chacun pour un utilisateur donné …
Pour obtenir une liste de tous les threads dans lesquels un utilisateur donné a participé, sortingés par message le plus récent en premier, avec uniquement le message le plus récent affiché (1 message par thread), vous utiliserez une requête similaire à celle ci-dessus, sauf au lieu de filtrer les messages par leur FK sur le thread concerné, vous filtrez les messages par une sous-requête qui trouve le dernier message dans chaque thread auquel l’utilisateur concerné a participé. Cela ressemblerait à ceci:
SELECT Message.MessageId , Message.CreateDate , Message.Body , Login.Username , (SELECT MessageReadState.ReadDate FROM MessageReadState WHERE MessageReadState.MessageId = Message.MessageId and MessageReadState.LoginId = 2) AS ReadState FROM Message INNER JOIN Login ON Message.SenderLoginId = Login.LoginId WHERE ( Message.MessageId in ( SELECT Max(Message.MessageId) FROM MessageThreadParticipant INNER JOIN Message ON MessageThreadParticipant.MessageThreadId = Message.MessageThreadId WHERE MessageThreadParticipant.LoginId=2 GROUP BY MessageThreadParticipant.MessageThreadId ) ) ORDER BY Message.CreateDate DESC;
Selon Joel Brown, vous pouvez append la colonne LAST_MESSAGE_ID
dans la table THREAD, puis obtenir tous les threads avec les derniers messages SQL devient très simple. Vous devez mettre à jour cette colonne lorsque chaque message est envoyé.
Obtenir tous les threads avec le dernier message dans chacun pour un utilisateur donné
SELECT * FROM THREAD T INNER JOIN MESSAGE M ON T.LAST_MESSAGE_ID=M.MESSAGE_ID INNER JOIN USER SENDER ON M.USER_ID=SENDER.USER_ID LEFT JOIN MessageReadState MRS ON M.MESSAGE_ID=MRS.MESSAGE_ID AND MRS.USER_ID=2