Mon objectif:
L'application Web (similaire à Google Drive) dispose de 2 écrans.
Le premier écran est "Mon histoire" qui affiche tous les documents d'histoire dont je suis le propriétaire.
Le deuxième écran est "Partagé avec moi" qui affiche tous les documents d'histoire que je suis lecteur, écrivain ou commentateur.
Nous avons ceci /stories/{storyid}
{
title: "A Great Story",
content: "Once upon a time ...",
roles: {
alice: "owner",
bob: "reader",
david: "writer",
jane: "commenter"
// ...
}
}
Référence complète de la structure de données: https://firebase.google.com/docs/firestore/solutions/role-based-access
Question: Comment rédiger la requête ci-dessous pour atteindre l'objectif ci-dessus?
db
.collection('stories')
.where(`roles.${uid}`, '==', 'owner')
La requête ci-dessus ne fonctionne PAS car elle nécessitera que Firestore indexe les rôles.alice, roles.bob, roles.david, roles.jane et rôles. [All_uid].
Edit # 1: Trouvé une publication connexe (sans réponse) demandant des informations sur Firestore interrogeant avec des rôles
Vous ne pouvez pas y parvenir avec votre structure de base de données réelle de manière à ce que vous n'ayez pas besoin de créer un index pour chaque utilisateur séparément. Pour résoudre ce problème, vous devez dupliquer vos données. Cette pratique est appelée denormalization
et est une pratique courante en ce qui concerne Firebase. Si vous êtes nouveau dans les bases de données NoQSL, je vous recommande de voir cette vidéo, la dénormalisation est normale avec la base de données Firebase pour une meilleure compréhension. C'est pour la base de données en temps réel Firebase mais les mêmes règles s'appliquent à Cloud Firestore.
De plus, lorsque vous dupliquez des données, il y a une chose à garder à l'esprit. De la même manière que vous ajoutez des données, vous devez les maintenir. En d'autres termes, si vous souhaitez mettre à jour/supprimer un élément, vous devez le faire dans tous les endroits où il existe.
Cela étant dit, vous devez créer une autre collection nommée userStories
, où vous devez ajouter comme documents toutes les histoires où un utilisateur est owner
. Votre structure de base de données devrait donc ressembler à ceci:
Firestore-root
|
--- userStories (collection)
|
--- uid (document)
|
--- allStories (collection)
|
--- storyId
|
--- role: "owner"
Donc, une requête comme celle-ci:
db.collection('userStories').doc(${uid})
.collection('allStories').where(`role`, '==', 'owner');
Fonctionnera parfaitement bien.
Ce n'est pas possible, nous devons donc dupliquer les données dans NoSQL.
Une structure de données possible est
/ stories/{storyid}
{
title: "A Great Story",
content: "Once upon a time ...",
roles: {
alice: "owner",
bob: "reader",
david: "writer",
jane: "commenter",
mary: "writer",
// ...
},
owner: "alice", // newly added
shared: ["bob", "david", "jane", "mary"] // newly added
// alice, bob, david, jane, mary are firebase auth uid
}
Nous pouvons donc interroger l'interface utilisateur de l'application Web "Mon histoire"
db
.collection('stories')
.where('owner', '==', uid)
Bien que nous puissions rechercher l'interface utilisateur de l'application Web "Partagé avec moi"
db
.collection('stories')
.where('shared', 'array_contains', uid)
La réponse est inspirée des commentaires de @Doug Stevenson.
Veuillez me faire savoir si je me trompe, mais il semble que votre requête devrait réellement fonctionner. à titre d'expérience, j'ai ajouté la structure que vous avez donnée dans la question et effectué la requête avec succès dans la console Firebase.
N'est-ce pas ce que vous recherchez? J'ai également vérifié que l'opérateur "in" fonctionne également pour ce cas. De cette façon, vous pouvez demander quelles histoires l'utilisateur est propriétaire et commentateur.