80 votes

Firestore - comment structurer un système d'alimentation et de suivi

J'ai été en utilisant Firebase en temps réel de la base de données pour mon test application de réseau social dans lequel vous pouvez simplement suivre et de recevoir du courrier de personnes que vous suivez. Traditionnelle réseau social. J'ai structuré ma base de données à quelque chose comme ça-

Users
--USER_ID_1
----name
----email
--USER_ID_2
----name
----email

Posts
--POST_ID_1
----image
----userid
----date
--POST_ID_2
----image
----userid
----date

Timeline
--User_ID_1
----POST_ID_2
------date
----POST_ID_1
------date

J'ai aussi un autre nœud "Contenu" qui vient de contenus id de tous les utilisateur de poste. Ainsi, si "A" suivi "B" que tous les id de B, où a ajouté à la Timeline. Et si B posté quelque chose qu'il a également été ajouté à l'ensemble de ses disciple de montage.

Maintenant, c'était ma solution en temps réel de la base de données mais il est clair que certains ont des problèmes d'évolutivité

  • si quelqu'un avoir de 10 000 followers qu'un nouveau poste a été ajouté à tous les 10 000 adepte de Montage.
  • Si quelqu'un a grande quantité de messages que chaque nouvel adepte reçu tous ces messages dans son Calendrier.

Ce sont quelques-uns des problèmes.

Maintenant, je pense à cette chose sur firestore que son prétendu "Évolutive". Alors, comment dois-je de la structure de ma base de données de sorte que les problèmes que j'ai rencontrés en temps réel de la base de données peut être éliminé dans firestore.

77voto

Alex Mamo Points 44420

J'ai vu votre question, un peu plus tard, mais je vais aussi essayer de vous fournir la meilleure structure de base de données je pense. Donc espérons que vous trouverez cette réponse utile.

Je suis en train de penser à un schéma qu'il y a trois niveau supérieur collections users, users that a user is following et posts:

Firestore-root
   |
   --- users (collection)
   |     |
   |     --- uid (documents)
   |          |
   |          --- name: "User Name"
   |          |
   |          --- email: "email@email.com"
   |
   --- following (collection)
   |      |
   |      --- uid (document)
   |           |
   |           --- userFollowing (collection)
   |                 |
   |                 --- uid (documents)
   |                 |
   |                 --- uid (documents)
   |
   --- posts (collection)
         |
         --- uid (documents)
              |
              --- userPosts (collection)
                    |
                    --- postId (documents)
                    |     |
                    |     --- title: "Post Title"
                    |     |
                    |     --- date: September 03, 2018 at 6:16:58 PM UTC+3
                    |
                    --- postId (documents)
                          |
                          --- title: "Post Title"
                          |
                          --- date: September 03, 2018 at 6:16:58 PM UTC+3

si quelqu'un avoir de 10 000 followers qu'un nouveau poste a été ajouté à tous les 10 000 adepte de Montage.

Qui ne sera pas du tout un problème parce que c'est la raison pour laquelle les collections sont ment dans Firestore. Selon la documentation officielle de la modélisation d'un Nuage Firestore base de données:

Cloud Firestore est optimisé pour le stockage de grandes collections de documents de petite taille.

C'est la raison pour laquelle j'ai ajouté userFollowing comme un ensemble et non comme un simple objet/map qui peut contenir d'autres objets. Rappelez-vous, la taille maximale d'un document selon la documentation officielle concernant les limites de quotas et de est - 1 MiB (1,048,576 bytes). Dans le cas de la collecte, il n'y a pas de limitation concernant le nombre de documents sous forme de collection. En fait, pour ce genre de structures est Firestore optimisé pour.

Donc le fait de les avoir 10.000 adeptes de cette manière, fonctionne parfaitement bien. En outre, vous pouvez interroger la base de données de telle manière à ne pas être nécessaire de copier quoi que ce soit n'importe où.

Comme vous pouvez le voir, la base de données est assez bien dénormalisée vous permettant de faire des requêtes très simples. Prenons un exemple, mais avant nous allons créer une connexion à la base de données et obtenir l' uid de l'utilisateur en utilisant les lignes de code suivantes:

FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();

Si vous souhaitez interroger la base de données pour obtenir tous les utilisateurs un utilisateur est la suivante, vous pouvez utiliser un get() appel sur la référence suivante:

CollectionReference userFollowingRef = rootRef.collection("following/" + uid + "/userFollowing");

Donc, dans cette façon, vous pouvez obtenir tous les objets utilisateur d'un utilisateur est la suivante. Ayant leur uid vous pouvez simplement obtenir tous leurs posts.

Disons que vous souhaitez obtenir sur votre timeline les trois derniers messages de chaque utilisateur. La clé pour résoudre ce problème, lors de l'utilisation de très grands ensembles de données est de charger les données en segments plus petits. Je l'ai expliqué dans ma réponse de ce post un recommandé de la façon dont vous pouvez paginer les requêtes en combinant requête curseurs avec l' limit() méthode. Je vous recommandons également de prendre un coup d'oeil à cette vidéo pour une meilleure compréhension. Donc, pour obtenir les trois derniers messages de tous les utilisateurs, vous devriez envisager d'utiliser cette solution. Donc, vous devez d'abord obtenir les 15 premiers objets utilisateur que vous suivez et puis, sur la base de leur uid, pour obtenir leur dernière création de trois postes. Pour obtenir la dernière création de trois postes d'un seul utilisateur, veuillez utiliser la requête suivante:

Query query = rootRef.collection("posts/" + uid + "/userPosts").orderBy("date", Query.Direction.DESCENDING)).limit(3);

Comme vous le défilement vers le bas, charge 15 autres objets utilisateur et d'obtenir leur dernière création de trois postes et ainsi de suite. À côté de l' date vous pouvez également ajouter d'autres propriétés de votre post objet, comme le nombre de likes, commentaires, partages et ainsi de suite.

Si quelqu'un a grande quantité de messages que chaque nouvel adepte reçu tous ces messages dans son Calendrier.

Aucun moyen. Il n'est pas nécessaire de faire quelque chose comme ça. J'ai déjà expliqué plus haut pourquoi.

Modifier Le 20 Mai 2019:

Une autre solution pour optimiser le fonctionnement dans lequel l'utilisateur doit voir tous les messages récents de tout le monde, il les a suivi, est de stocker les messages que l'utilisateur doit voir dans un document de l'utilisateur.

Donc, si nous prenons un exemple, disons que facebook, vous aurez besoin d'avoir un document contenant le facebook de l'alimentation pour chaque utilisateur. Cependant, si il y a trop de données qu'un seul document peut contenir (1 Mib), vous avez besoin de mettre les données dans une collection, comme expliqué ci-dessus.

14voto

Niyas Points 232

Il y a deux situations

  1. Les utilisateurs de votre application ont un petit nombre de disciples.

  2. Les utilisateurs de votre application ont un grand nombre de disciples. Si nous voulons pour stocker l'ensemble des adeptes dans un seul tableau dans un document unique dans firestore. Ensuite, il va frapper le firestore limite de 1 MiB par document.


  1. Dans le premier cas, chaque utilisateur doit conserver un document où sont stockés les abonnés de la liste dans un document unique dans un seul tableau. En utilisant arrayUnion() et arrayRemove() il est possible de gérer efficacement les adeptes de la liste. Et quand vous allez poster quelque chose dans votre journal, vous devez ajouter à la liste d'adeptes dans le post du document.

    Et utiliser la requête ci-dessous pour rechercher les posts

    postCollectionRef.whereArrayContains("followers", userUid).orderBy("date");
    
  2. Dans la seconde situation, vous avez juste besoin de casser de l'utilisateur document suivant en fonction de la taille ou du nombre de disciples de tableau. Après avoir atteint la taille du tableau à taille fixe la prochaine adepte de la pièce d'identité doit ajouter dans le document suivant. Et le premier document doit garder le champ "hasNext", qui stocke une valeur booléenne. Lors de l'ajout d'un nouveau message, vous devez double post document et de chaque document composé de disciples liste des pauses plus tôt. Et nous pouvons faire la même requête qui est donné ci-dessus pour récupérer les documents.

5voto

Tsabary Points 416

J'ai eu du mal peu avec les solutions suggérées elle, principalement en raison d'une lacune technique, j'ai donc pensé à une autre solution qui fonctionne pour moi.

Pour chaque utilisateur, j'ai un document avec tous les comptes qu'ils suivent, mais également toute une liste de tous les comptes qui suivent cet utilisateur.

Lorsque l'application démarre, je choppe la liste des comptes qui suivent ce courant de l'utilisateur, et lorsqu'un utilisateur fait un post, une partie de la post objet est la matrice de tous les utilisateurs qui suivent.

Lorsque l'utilisateur B veut aussi obtenir tous les postes des personnes qu'ils suivent, je viens d'annonces à la requête d'un simple whereArrayContains("followers", currentUser.uid).

J'aime cette approche car elle permet encore de moi pour classer les résultats par d'autres paramètres que je veux.

Basé sur:

  • 1 mo par document, qui, par une recherche google que j'ai fait semble contenir de 1 048 576 chaarecters.
  • Le fait que Firestore généré Uid semblent être de l'ordre de 28 caractères.
  • Le reste de l'info dans l'objet ne prend pas trop de taille.

Cette approche de travail pour les utilisateurs qui ont jusqu'à environ de 37 000 adeptes.

1voto

Je suis allé à travers les Firebase de la documentation, et je suis confus quant à pourquoi l'a suggéré la mise en œuvre au https://firebase.google.com/docs/database/android/structure-data#fanout ne fonctionne pas dans votre cas. Quelque chose comme ceci:

users
--userid(somedude)
---name
---etc
---leaders: 
----someotherdude
----someotherotherdude

leaders:
--userid(someotherdude)
---datelastupdated
---followers
----somedude
----thatotherdude
---posts
----postid

posts
--postid
---date
---image
---contentid

postcontent
--contentid
---content

Le guide cite "C'est une redondance nécessaire pour les deux sens de relations. Il vous permet de rapidement et efficacement chercher de l'Ada adhésions, même lorsque la liste des utilisateurs ou des groupes d'échelles dans les millions.", donc, il ne semble pas que l'évolutivité est exclusivement un Firestore chose.

Sauf que je suis absent quelque chose le problème principal semble être l'existence de la timeline, le nœud lui-même. J'ai ce qu'il le rend plus facile à générer une vue d'un utilisateur en particulier de la timeline, mais c'est au prix d'avoir à maintenir l'ensemble de ces relations et est considérablement retarder votre projet. Est-il trop inefficace d'utiliser des requêtes pour construire une frise chronologique sur la volée à partir d'une structure similaire à celle ci-dessus, basé sur un utilisateur soumis?

-3voto

smashrain Points 31

Vous devez maintenir des relations entre les abonnés:

 Followers
-leading_id
-follower_id
-created_at
 

Ensuite, je pense que vous n’avez pas besoin d’un tableau chronologique. Lorsque vous ouvrez un flux, obtenez tous les abonnés et rejoignez leurs publications. Vous pouvez également utiliser une sorte d'ordre et de filtre dans la demande.

Dans votre structure, le tableau chronologique duplique les informations sur les publications. Je pense que ce n'est pas normal pour la base de données.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X