140 votes

Sous-collections de requêtes Firestore

Je pensais avoir lu que vous pouviez interroger des sous-collections avec le nouveau Firebase Firestore, mais je ne vois pas d'exemples. Par exemple, j'ai configuré mon Firestore de la manière suivante :

  • Danses [collection]
    • nom de la danse
    • Chansons [collection]
      • nom de la chanson

Comment pourrais-je demander "Trouver toutes les danses où songName == 'X'" ?

171voto

Gil Gilbert Points 4404

Mise à jour 2019-05-07

Aujourd'hui, nous avons publié requêtes de groupes de collections qui vous permettent d'effectuer des recherches dans des sous-collections.

Ainsi, par exemple, dans le SDK web :

db.collectionGroup('Songs')
  .where('songName', '==', 'X')
  .get()

Cela correspondrait aux documents de toute collection dont la dernière partie du chemin de la collection est "Songs".

Votre question initiale était de trouver danses où songName == 'X', et ce n'est toujours pas possible directement, cependant, pour chaque chanson qui correspond, vous pouvez charger son parent.

Réponse originale

Il s'agit d'une fonctionnalité qui n'existe pas encore. Elle s'appelle "collection group query" et vous permettrait d'interroger toutes les chansons indépendamment de la danse qui les contient. C'est une fonctionnalité que nous avons l'intention de prendre en charge, mais nous n'avons pas de calendrier précis quant à son arrivée.

La structure alternative à ce stade est de faire des chansons une collection de premier niveau et de faire de la danse dont la chanson fait partie une propriété de la chanson.

0 votes

Est-ce que vous feriez référence à la danse de la chanson en utilisant une référence de magasin de feu ? Pouvez-vous effectuer des recherches à partir de ces références ?

0 votes

C'est à vous de décider si vous utilisez ou non une référence Firestore. Vous pouvez effectuer des recherches à l'aide de ces références. Si vous souhaitez uniquement utiliser les références pour rechercher la danse, une référence est suffisante. Si vous voulez être en mesure d'afficher quelque chose sur la danse à partir d'une chanson sans rechercher la danse, je n'utiliserais pas de référence. C'est le problème classique de dénormalisation de nosql.

0 votes

Mon problème est donc que je veux faire une recherche par nom de danse ET par nom de chanson. Une seule danse peut avoir plusieurs chansons associées à elle. De plus, je dois être capable de noter la danse ET la chanson associée à la danse. Par exemple, la chanson A et la chanson B sont associées à la danse A. La danse A est amusante, 5 étoiles - MAIS la chanson A ne convient pas vraiment (vote négatif), mais la chanson B oui (vote positif). Je vais donc certainement utiliser les fonctions Firebase pour suivre l'évaluation moyenne des deux. Mais j'ai encore besoin de pouvoir faire une requête WHERE songName = 'X' et aussi WHERE danceName = 'Y'. Firestore sera-t-il en mesure de prendre en charge cette fonctionnalité à l'avenir ?

22voto

norgematos Points 452

UPDATE Firestore prend désormais en charge les tableaux-contenus

Avoir ces documents

    {danceName: 'Danca name 1', songName: ['Title1','Title2']}
    {danceName: 'Danca name 2', songName: ['Title3']}

faites-le de cette façon

collection("Dances")
    .where("songName", "array-contains", "Title1")
    .get()...

@Nelson.b.austin Puisque firestore n'a pas encore cela, je vous suggère d'avoir une structure plate, c'est-à-dire :

Dances = {
    danceName: 'Dance name 1',
    songName_Title1: true,
    songName_Title2: true,
    songName_Title3: false
}

En l'ayant de cette façon, vous pouvez le faire :

var songTitle = 'Title1';
var dances = db.collection("Dances");
var query = dances.where("songName_"+songTitle, "==", true);

J'espère que cela vous aidera.

2 votes

Ce qui est songName_Title3: false utile ? si je ne me trompe pas, il ne peut être utilisé que pour rechercher des danses qui n'ont pas de nom de chanson spécifique en supposant que nous ayons besoin d'une songName_Title3: false de faire dances.where("songName_"+songTitle, "==", false); avec de tels résultats, il ne serait pas logique que chaque danse ait des indicateurs booléens pour chaque nom de chanson possible...

0 votes

C'est très bien, mais les documents sont limités à 1 Mo. Par conséquent, si vous devez associer une longue liste de chaînes de caractères ou autre à un document spécifique, vous ne pouvez pas utiliser cette approche.

0 votes

@Supertecnoboff Cela semble devoir être une liste de chaînes de caractères terriblement grande et longue. Quelle est la performance de cette requête "array_contains" et quelles sont les alternatives plus performantes ?

17voto

Matthew Mullin Points 2160

MISE À JOUR 2019

Firestore a publié des requêtes de groupe de collection. Voir la réponse de Gil ci-dessus ou le site officiel de Documentation sur les requêtes de groupes de collections


Réponse précédente

Comme l'a déclaré Gil Gilbert, il semble que requêtes de groupes de collections est actuellement en cours de réalisation. En attendant, il est probablement préférable d'utiliser des collections de niveau racine et de créer des liens entre ces collections en utilisant les UID des documents.

Pour ceux qui ne le savent pas encore, Jeff Delaney propose des guides et des ressources incroyables pour tous ceux qui travaillent avec Firebase (et Angular) sur le site suivant AngularFirebase .

Firestore NoSQL Modélisation de données relationnelles - Il explique ici les bases de la structuration des bases de données NoSQL et Firestore.

Modélisation avancée des données avec Firestore par exemple - Ce sont des techniques plus avancées à garder en mémoire. Une excellente lecture pour ceux qui veulent passer au niveau supérieur de leurs compétences en matière de Firestore.

16voto

dmartins Points 161

Et si vous stockiez les chansons comme un objet plutôt que comme une collection ? Chaque danse en tant que, avec les chansons comme champ : type Object (pas une collection)

{
  danceName: "My Dance",
  songs: {
    "aNameOfASong": true,
    "aNameOfAnotherSong": true,
  }
}

alors vous pourriez rechercher toutes les danses avec aNameOfASong :

db.collection('Dances')
  .where('songs.aNameOfASong', '==', true)
  .get()
  .then(function(querySnapshot) {
    querySnapshot.forEach(function(doc) {
      console.log(doc.id, " => ", doc.data());
    });
   })
   .catch(function(error) {
     console.log("Error getting documents: ", error);
    });

7 votes

Cette solution fonctionnerait mais elle n'est pas évolutive si le nombre de chansons est important ou s'il peut augmenter de manière dynamique. Cela augmenterait la taille du document et affecterait les performances de lecture/écriture. Vous trouverez plus d'informations à ce sujet dans la documentation de Firebase dont le lien figure ci-dessous (voir la dernière section "Limitations" de la page). firebase.google.com/docs/firestore/solutions/arrays

3voto

ggDeGreat Points 131

Limites des requêtes

Cloud Firestore ne prend pas en charge les types de requêtes suivants :

  1. Requêtes avec des filtres de plage sur différents champs.

  2. Requêtes uniques sur plusieurs collections ou sous-collections. Chaque requête s'exécute sur une seule collection de documents. Pour plus d'informations informations sur l'impact de la structure de vos données sur vos requêtes, consultez la rubrique Choisir une structure de données .

  3. Requêtes logiques OR. Dans ce cas, vous devez créer une requête distincte pour chaque condition OR et fusionner les résultats des requêtes dans votre application.

  4. Requêtes avec une clause !=. Dans ce cas, vous devez diviser la requête en une requête supérieure et une requête inférieure. Par exemple, bien que la clause de requête where("age", "!=", "30") ne soit pas prise en charge, vous pouvez obtenir le même ensemble de résultats en combinant deux requêtes, l'une contenant la clause where("age", "<", "30") et une autre avec la clause where("age", ">", 30).

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