web-dev-qa-db-fra.com

Firestore Google - Comment obtenir des documents par plusieurs identifiants en un aller-retour?

Je me demande s’il est possible d’obtenir plusieurs documents par liste d’identifiants lors d’un aller-retour (appel réseau) vers le magasin Firestore.

39
Joon

si vous êtes dans Node:

https://github.com/googleapis/nodejs-firestore/blob/master/dev/src/index.ts#L701

/**
* Retrieves multiple documents from Firestore.
*
* @param {...DocumentReference} documents - The document references
* to receive.
* @returns {Promise<Array.<DocumentSnapshot>>} A Promise that
* contains an array with the resulting document snapshots.
*
* @example
* let documentRef1 = firestore.doc('col/doc1');
* let documentRef2 = firestore.doc('col/doc2');
*
* firestore.getAll(documentRef1, documentRef2).then(docs => {
*   console.log(`First document: ${JSON.stringify(docs[0])}`);
*   console.log(`Second document: ${JSON.stringify(docs[1])}`);
* });
*/
33
Nick Franceschina

Non, il n’existe actuellement aucun moyen de regrouper plusieurs demandes de lecture par lot à l’aide du kit SDK Cloud Firestore et donc aucun moyen de garantir que vous pouvez lire toutes les données en même temps.

Cependant, comme Frank van Puffelen l’a dit dans les commentaires ci-dessus, cela ne veut pas dire que l’obtention de 3 documents sera 3 fois plus lente que celle d’un seul document. Il est préférable d'effectuer vos propres mesures avant de tirer une conclusion ici.

8
Sam Stern

Vous pouvez utiliser une fonction comme celle-ci:

function getById (path, id) {
  return firestore.getAll(
    [].concat(ids).map(id => firestore.doc(`${path}/${id}`)
  )
}

Il peut être appelé avec un seul identifiant:

getById('collection', 'some_id')

ou un tableau d'identifiants:

getById('collection', ['some_id', 'some_other_id'])
4
JP de la Torre

La meilleure façon de le faire est sûrement d’implémenter la requête de Firestore dans une fonction de cloud computing. Il n'y aurait alors qu'un seul appel du client à l'aller-retour, ce qui semble être ce que vous demandez.

De toute façon, vous voulez vraiment garder toute votre logique d’accès aux données comme du côté serveur.

En interne, il y aura probablement le même nombre d'appels à Firebase lui-même, mais ils seront tous sur les interconnexions ultra-rapides de Google, plutôt que sur le réseau externe, et combinés au traitement en pipeline que Frank van Puffelen a expliqué, vous devriez obtenir d'excellentes performances de cette approche.

4
Chris Wilson

En pratique, vous utiliseriez firestore.getAll like this

async getUsers({userIds}) {
    const refs = userIds.map(id => this.firestore.doc(`users/${id}`))
    const users = await this.firestore.getAll(...refs)
    console.log(users.map(doc => doc.data()))
}

ou avec une syntaxe de promesse

getUsers({userIds}) {
    const refs = userIds.map(id => this.firestore.doc(`users/${id}`))
    this.firestore.getAll(...refs).then(users => console.log(users.map(doc => doc.data())))
}
0
Sebastian

Cela ne semble pas être possible à Firestore pour le moment. Je ne comprends pas pourquoi la réponse d'Alexandre est acceptée, la solution qu'il propose ne fait que renvoyer tous les documents de la collection "utilisateurs".

Selon ce que vous devez faire, vous devriez envisager de dupliquer les données pertinentes que vous devez afficher et demander uniquement un document complet en cas de besoin.

0
Horea

Le mieux que vous puissiez faire estpasutilisez Promise.all car votre client doit alors attendre .all les lectures avant de continuer.

Itérer les lectures et les laisser résoudre indépendamment. Du côté du client, cela se résume probablement à l'interface utilisateur ayant plusieurs images du chargeur de progression résolues en valeurs indépendamment. Cependant, cela vaut mieux que de geler tout le client jusqu'à ce que .all soit résolu.

Par conséquent, exportez immédiatement tous les résultats synchrones dans la vue, puis laissez les résultats asynchrones entrer au fur et à mesure de leur résolution, individuellement. Cela peut sembler une petite distinction, mais si votre client a une connectivité Internet médiocre (comme ce que j'ai actuellement dans ce café), geler toute l'expérience client pendant plusieurs secondes entraînera probablement une expérience de "cette application est nulle".

0
Ron Royston