web-dev-qa-db-fra.com

Utilisation de requêtes uniques imbriquées dans Firestore

Récemment, j'ai déplacé mon modèle de données de Firebase vers Firestore. Tout mon code fonctionne, mais j'ai de gros problèmes concernant mes requêtes imbriquées pour récupérer certaines données. Voici le point:

En ce moment, mon modèle de données pour cette partie ressemble à ceci (Oui! Un autre exemple de followers/flux):

{
  "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 messages du flux d'un utilisateur, je dois interroger de la manière suivante:

  • Obtenir la dernière commande de documents X par horodatage à partir de mon flux

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

  • Après cela, je devrais faire une seule requête de chaque message récupéré de la liste: workoutPostCol.document(postId)

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

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

En ce moment, tout fonctionne, mais en pensant que le prix de Firestore dépend du nombre d'appels de base de données, et aussi que cela ne rend pas mes requêtes plus simples, je ne sais pas si c'est juste que mon le modèle de données n'est pas bon pour ce type de base de données et je devrais revenir à SQL normal ou simplement revenir à Firebase.

Remarque: Je sais que TOUT, il serait beaucoup plus facile de déplacer ces sous-collections de likes, de flux, etc. vers des listes dans mon utilisateur ou mes documents, mais la limite d'un document est 1 Mo et si cela se développe trop, il se plantera à l'avenir. En revanche, Firestore n'autorise pas (encore) les requêtes de sous-document ou une clause OR utilisant 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 de relation ID's Pour créer joins et queries dans leur Collections, utilisez Arraylists serait génial, mais la limite de 1 Mo le limite à beaucoup.

J'espère que quelqu'un pourra clarifier cela, ou au moins m'apprendre quelque chose de nouveau; peut-être que mon modèle est juste de la merde et qu'il existe un moyen simple et plus facile de le faire? Ou peut-être que mon modèle n'est pas possible pour une base de données non SQL.

27

Je ne suis pas sûr à 100% si cela résout le problème entièrement, car il peut y avoir des cas Edge pour votre utilisation. Mais avec une réflexion rapide de 5 minutes, je pense que ce qui suit pourrait résoudre votre problème:

Vous pouvez envisager d'utiliser un modèle similaire à celui d'Instagram. Si ma mémoire est bonne, ils utilisent une collection basée sur events. Par events dans ce contexte spécifique, je veux dire toutes les actions que l'utilisateur prend. Donc un comment est un événement, un like est un événement etc.

Ainsi, 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 page utilisateur-bio, vous interrogeriez users.

Pour le fil d'actualités, vous interrogerez posts pour tous les messages par ID utilisateur suivis par votre utilisateur au cours du dernier jour (ou à n'importe quelle période donnée),

Pour la page du flux d'activité (commentaires/likes, etc.), vous interrogerez events qui sont pertinents pour votre ID utilisateur limité au dernier jour (ou à une période donnée)

Enfin, interrogez les prochains jours pour les publications/événements pendant que l'utilisateur défile (ou s'il n'y a pas de nouvelle activité ces jours-là)

Encore une fois, ce n'est qu'une pensée rapide, je sais que les anciens des SOF ont l'habitude de les crucifier habituellement, alors pardonnez-moi mes collègues membres des SOF si cette réponse a des défauts :)

J'espère que ça aide Francisco,

Bonne chance!

19
johnozbay