Firebase requête si l'enfant de l'enfant contient une valeur
la structure du tableau est la suivante:
- chats
- -- > randomId
- -- > -- > participants
- -->-->--> 0: 'nom1 '
- -->-->--> 1: 'nom2'
- -- > -- > chatItems
etc
ce que j'essaie de faire est d'interroger la table des chats pour trouver tous les chats qui tiennent un participant par un passé dans nom d'utilisateur de la chaîne.
Voici ce que j'ai jusqu'à présent:
subscribeChats(username: string) {
return this.af.database.list('chats', {
query: {
orderByChild: 'participants',
equalTo: username, // How to check if participants contain username
}
});
}
1 réponses
votre structure de données actuelle est excellente pour rechercher les participants d'un chat spécifique. Ce n'est toutefois pas une très bonne structure pour chercher l'inverse: les conversations dans lesquelles un utilisateur participe.
quelques problèmes ici:
- vous êtes le stockage d'un set comme un tableau
- vous pouvez seulement l'index sur les chemins fixes
Set vs array
un chat peut avoir plusieurs participants, donc vous modélisez ceci comme un tableau. Mais ce n'est pas la structure de données idéale. Probablement chaque participant ne peut être dans le chat une fois. Mais en utilisant un tableau, j'aurais pu:
participants: ["puf", "puf"]
, C'est clairement pas ce que vous avez à l'esprit, mais la structure de données permet. Vous pouvez essayer de sécuriser cela dans le code et les règles de sécurité, mais ce serait plus facile si vous commenciez avec une structure de données qui correspond implicitement à votre modèle mieux.
Ma règle d'or: si vous vous trouvez écrire array.contains()
, vous devriez être en utilisant un ensemble .
un ensemble est une structure où chaque enfant peut être présent au plus une fois, donc il protège naturellement contre les doublons. Dans Firebase vous modéliseriez un ensemble comme:
participants: {
"puf": true
}
le true
ici est vraiment juste une valeur fictive: la chose importante est que nous avons déplacé le nom à la clé. Maintenant, si Je voudrais essayer de rejoindre cette conversation à nouveau, il serait un noop:
participants: {
"puf": true
}
Et quand tu allais rejoindre:
participants: {
"john": true,
"puf": true
}
c'est la représentation la plus directe de votre exigence: une collection qui ne peut contenir chaque participant qu'une seule fois.
vous ne pouvez indexer que les propriétés connues
avec la structure ci-dessus, vous pourrait requête pour les chats que vous êtes avec:
ref.child("chats").orderByChild("participants/john").equalTo(true)
le problème est que cela nécessite que vous définissiez un index sur 'participants / john":
{
"rules": {
"chats": {
"$chatid": {
"participants": {
".indexOn": ["john", "puf"]
}
}
}
}
}
cela va fonctionner et effectuer grand. Mais maintenant chaque fois que quelqu'un de nouveau rejoint l'application de chat, vous aurez besoin d'ajouter un autre index. C'est clairement pas une évolutive modèle. Nous aurons besoin de changer notre structure de données pour permettre la requête que vous voulez.
Inverser l'index-tirer les catégories vers le haut, aplatir l'arbre
Deuxième règle empirique: modéliser vos données pour refléter ce que vous montrez dans votre application .
comme vous cherchez à montrer une liste de salons de discussion pour un utilisateur, stockez les salons de discussion pour chaque utilisateur:
userChatrooms: {
john: {
chatRoom1: true,
chatRoom2: true
},
puf: {
chatRoom1: true,
chatRoom3: true
}
}
Maintenant, vous pouvez simplement déterminer votre liste de salons de chat avec:
ref.child("userChatrooms").child("john")
et ensuite boucler les touches pour obtenir chaque chambre.
Vous aimerez avoir deux listes dans votre app:
- la liste des salles de chat pour un utilisateur spécifique
- la liste des participants dans un salon de discussion spécifique
dans ce cas, vous aurez aussi les deux listes dans la base de données.
chatroomUsers
chatroom1
user1: true
user2: true
chatroom2
user1: true
user3: true
userChatrooms
user1:
chatroom1: true
chatroom2: true
user2:
chatroom1: true
user2:
chatroom2: true
j'ai tiré les deux listes au niveau supérieur de l'arbre, puisque Firebase recommande contre les données de nidification.
avoir les deux listes est tout à fait normal dans NoSQL solution. Dans l'exemple ci-dessus, nous appellerions userChatrooms
l'indice inversé de chatroomsUsers
.