31 votes

De travail avec imbriqué unique requêtes dans Firestore

Récemment, j'ai déménagé mon modèle de données à partir de Firebase pour Firestore. Tout mon code fonctionne, mais je vais avoir des moches, des ennuis au sujet de mon requêtes imbriquées pour récupérer certaines données. Voici le point:

Droit maintenant, mon modèle de données pour cette partie ressemble à ça(Oui! Un autre des disciples/feed exemple):

{
  "Users": { //Collection
    "UserId1" : { //Document
      "Feed" : { //Subcollection of Id of posts from users this user Follow
        "PostId1" : { //Document
          "timeStamp" : "SomeDate"
        },
        "PostId2" : {
          "timeStamp" : "SomeDate"
        },
        "PostId3" : {
          "timeStamp" : "SomeDate"
        }
      }
      //Some data
    }
  },
  "Posts":{ //Collection
    "PostId1":{ //Document
      "Comments" :{ //Subcollection
        "commentId" : { //Document
          "authorId": "UserId1"
          //comentsData
        }
      },
      "Likes" : { //Subcollection
        "UserId1" : { //Document
          "liked" : true
        }       
      }
    }
  }
}

Mon problème est que pour récupérer les Postes de l'alimentation d'un utilisateur je dois requête de la façon suivante:

  • Obtenir les X derniers documents donneur d'ordre par date de mon Alimentation

feedCol(userId).orderBy(CREATION_DATE, Query.Direction.DESCENDING).limit(limit)

  • Après cela, je dois faire une requête unique de chaque post (extrait de la liste: workoutPostCol.document(postId)

  • Maintenant, j'ai les données de chaque post, mais je veux tourné le nom d'utilisateur, de l'image, les points etc.. de l'auteur, qui est dans un autre Document, donc, encore une fois, je dois faire une autre requête unique pour chaque authorId récupérées dans la liste de postes userSocial(userId).document(toId)

  • Enfin, et pas le moins important, j'ai besoin de savoir si mon utilisateur actuel déjà aimé ce poste, donc j'ai besoin de faire une seule requête pour chaque poste(encore une fois) et de vérifier si mon nom d'utilisateur est à l'intérieur d' posts/likes/{userId}

Droit maintenant, tout fonctionne, mais en pensant que le prix de l' Firestore est en fonction du nombre d'appels de base de données, et aussi qu'il ne veut pas faire mes requêtes plus simples, je ne sais pas si c'est juste que mon modèle de données n'est pas bon pour ce genre de base de données et je devrais aller à la normale SQL ou juste de retour d' Firebase de nouveau.

Note: je sais que TOUT serait beaucoup plus facile de déplacer cette sous-groupes de "j'aime", les aliments, etc, à arraylists à l'intérieur de mon utilisateur ou afficher les documents, mais la limite d'un Document est de 1 mo et si cette croître pour beaucoup, Il va planter dans l'avenir. En revanche Firestore ne pas autoriser les sous-requêtes(encore) ou un OR de la clause à l'aide de plusieurs whereEqualTo.

J'ai lu beaucoup de messages d'utilisateurs qui ont des problèmes à la recherche d'un moyen simple de stocker ce type d' ID's relation pour en faire une joins et queries leur Collections, utilisez Arraylists serait génial, mais la limite de 1 MO limiter à beaucoup.

Espérons que quelqu'un sera en mesure de clarifier cela, ou au moins de m'enseigner quelque chose de nouveau; peut-être mon modèle est tout simplement de la merde et il ya un moyen simple et facile de faire cela? Ou peut-être que mon modèle n'est pas possible pour un non-sql base de données.

22voto

cozbay Points 13

Pas sûr à 100% si cela résout le problème, car il peut y avoir des cas limites pour votre utilisation. Mais avec 5 min de réfléchir rapidement, je sens que la suite pourrait résoudre votre problème :

Vous pouvez envisager d'utiliser un modèle similaire à Instagram de la. Si ma mémoire me sert bien, ce qu'ils utilisent est une events-en fonction de la collection. En events dans ce contexte précis, je veux dire toutes les actions que l'utilisateur prend. Ainsi, un comment est un événement, un like est un événement.

Cela permettrait de faire en sorte que vous aurez besoin de trois collections principales au total.

users
-- userID1
---- userdata (profile pic, bio etc.)
---- postsByUser : [postID1, postID2]
---- followedBy : [userID2, ... ]
---- following : [userID2, ... ]
-- userID2
---- userdata (profile pic, bio etc.)


posts
-- postID1 (timestamp, so it's sortable)
---- contents
---- author : userID1
---- authorPic : authorPicUrl
---- authorPoints : 12345
---- taggedUsers : []
---- comments
------ comment1 : { copy of comment event }
---- likes : [userID1, userID2]
-- postID2 (timestamp)
---- contents
... 


events
-- eventID1
---- type : comment
---- timestamp
---- byWhom : userID
---- toWhichPost : postID
---- contents : comment-text
-- eventID2
---- type : like
---- timestamp
---- byWhom : userID
---- toWhichPost : postID

Pour votre utilisateur-page bio, vous serait interroger users.

Pour le flux de nouvelles, vous serait interroger posts pour tous les postes par les noms d'utilisateur est votre nom d'utilisateur suivant dans le dernier 1 jour (ou d'un timespan),

Pour le fil d'activité de la page (commentaires / likes etc.) vous serait interroger events qui sont pertinentes à votre nom d'utilisateur limité à la durée de 1 jour (ou d'un timespan)

Enfin interroger les prochains jours pour les articles / événements que l'utilisateur fait défiler (ou si il n'y a pas de nouvelle activité dans ces jours)

Encore une fois, ce n'est qu'une pensée rapide, je sais que les anciens des forces spéciales ont l'habitude de crucifying ces habituellement, pardonne-moi donc les autres membres de SOF si cette réponse a des défauts :)

Espérons que cela aide Francisco,

Bonne chance!

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