web-dev-qa-db-fra.com

Sous-collections de requêtes Firestore

Je pensais avoir lu que vous pouviez interroger des sous-groupes avec le nouveau Firebase Firestore, mais je ne vois aucun exemple. Par exemple, ma configuration Firestore est la suivante:

  • Danses [collection]
    • danceName
    • Chansons [collection]
      • titre de chanson

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

74
Nelson.b.austin

C'est une fonctionnalité qui n'existe pas encore. Cela s'appelle une "requête de groupe de collection" et vous permettrait d'interroger toutes les chansons, quelle que soit leur danse. C’est quelque chose que nous avons l’intention de soutenir mais nous n’avons pas de calendrier précis à venir.

À ce stade, la structure alternative consiste à faire des chansons une collection de premier plan et à définir dans quelle danse la chanson fait partie d’une propriété de la chanson.

75
Gil Gilbert

UPDATE Maintenant Firestore supporte les tableaux

Avoir ces documents

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

le faire de cette façon

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

@ Nelson.b.austin Étant donné que Firestore ne l’a pas encore, je vous suggère d’avoir une structure plate, ce qui signifie:

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

Ainsi, vous pouvez le faire:

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

J'espère que ça aide.

14
norgematos

Que faire si vous stockez des chansons sous forme d'objet plutôt que sous forme de collection? Chaque danse en tant que, avec les chansons comme un champ: tapez Object (pas une collection)

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

alors vous pouvez interroger 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);
    });
13
dmartins

Comme l’a déclaré Gil Gilbert, il semble que les requêtes collection group soient actuellement en cours. En attendant, il est probablement préférable d'utiliser des collections de niveau racine et de simplement relier ces collections en utilisant les UID du document.

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

Firestore NoSQL Relational Data Modeling - Il explique ici les bases de la structuration de bases de données NoSQL et Firestore

Modélisation de données avancée avec Firestore par exemple - Ce sont des techniques plus avancées pour garder à l'esprit. Une excellente lecture pour ceux qui souhaitent améliorer leurs compétences en matière de Firestore

6
Matthew Mullin

Limites de la requête

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

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

  2. Requêtes uniques sur plusieurs collections ou sous-collections. Chaque requête est exécutée sur une seule collection de documents. Pour plus des informations sur la manière dont votre structure de données affecte vos requêtes, voir Choisissez 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 de la requête dans votre application.
  4. Requêtes avec une clause! =. Dans ce cas, vous devez scinder la requête en une requête supérieure à et une requête inférieure à. Par exemple, bien que la clause de requête où ("age", "! =", "30") n'est pas supportée, vous pouvez obtenir le même jeu de résultats en combinant deux requêtes, une avec la clause où ("âge", "<", "30") et un avec la clause où ("âge", ">", 30).
1
ggDeGreat
var songs = []    
db.collection('Dances')
      .where('songs.aNameOfASong', '==', true)
      .get()
      .then(function(querySnapshot) {
        var songLength = querySnapshot.size
        var i=0;
        querySnapshot.forEach(function(doc) {
           songs.Push(doc.data())
           i ++;
           if(songLength===i){
                console.log(songs
           }
          console.log(doc.id, " => ", doc.data());
        });
       })
       .catch(function(error) {
         console.log("Error getting documents: ", error);
        });
1
Alok Prusty

NEW UPDATE 8 juillet 2019:

db.collectionGroup('Songs')
  .where('songName', isEqualTo:'X')
  .get()
1
Nhật Trần

Il pourrait être préférable d’utiliser une structure de données plate.
La documentation précise les avantages et les inconvénients de différentes structures de données sur cette page .

Spécifiquement sur les limitations des structures avec des sous-collections:

Vous ne pouvez pas facilement supprimer des sous-groupes ou effectuer des requêtes composées sur plusieurs sous-groupes.

Contrasté avec les prétendus avantages d’une structure de données plate:

Les collections de niveau racine offrent une flexibilité et une évolutivité maximales, ainsi que des requêtes puissantes au sein de chaque collection.

1
MattClimbs

Vous pouvez toujours chercher comme ceci: -

this.key$ = new BehaviorSubject(null);

return this.key$.switchMap(key =>
  this.angFirestore
    .collection("dances").doc("danceName").collections("songs", ref =>
      ref
        .where("songName", "==", X)
    )
    .snapshotChanges()
    .map(actions => {
      if (actions.toString()) {
        return actions.map(a => {
          const data = a.payload.doc.data() as Dance;
          const id = a.payload.doc.id;
          return { id, ...data };
        });
      } else {
        return false;
      }
    })
);
0
Ankur Biswas