или с синтаксисом обещания

нтересно, можно ли получить несколько документов по списку идентификаторов за одну поездку (сетевой вызов) в Firestore.

 Joon14 окт. 2017 г., 00:08
К вашему сведению, под поездкой туда и обратно подразумевается один сетевой запрос к базе данных от клиента. Я спрашиваю, если несколько запросов автоматически группируются как одно и то же в Firestore, или несколько запросов выполняются как несколько циклов в параллельном режиме.
 Frank van Puffelen13 окт. 2017 г., 15:19
Не отправил бы их всех как единогоSELECT * FROM docs WHERE id IN (a,b,c) займет столько же времени? Я не вижу разницы, поскольку соединение устанавливается один раз, а остальное передается по конвейеру. Время (после первоначального установления соединения) является временем загрузки всех документов + 1 поездка туда и обратно, то же самое для обоих подходов. Если он ведет себя по-другому для вас, можете ли вы поделиться примером (как в моем связанном вопросе)?
 Joon13 окт. 2017 г., 23:53
Я думаю, что потерял тебя. Когда вы говорите, что это конвейерно, вы имеете в виду, что Firestore автоматически группирует и отправляет запросы на свой сервер за один прием в базу данных?
 Joon13 окт. 2017 г., 10:26
Допустим, мне нужны документыa, b, c сделать что-то. Я запрашиваю все три параллельно в отдельных запросах.a занимает 100 мс,b занимает 150 мс, иc занимает 3000 мс. В результате мне нужно подождать 3000 мс, чтобы выполнить задачу. Это будетmax из них. Это будет более рискованным, когда количество документов для извлечения будет большим. Зависит от состояния сети, думаю, это может стать проблемой.
 Frank van Puffelen13 окт. 2017 г., 05:22
Похоже, вы предполагаете, что обходные пути вызывают проблемы с производительностью в вашем приложении. Я бы не предполагал это. Firebase имеет историю выполнения штрафов в таких случаях, так как онконвейерные запросы, Хотя я не проверял, как Firestore ведет себя в этом сценарии, я хотел бы увидеть доказательства проблемы с производительностью, прежде чем предположить, что она существует.

Ответы на вопрос(7)

как это

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()))
}

или с синтаксисом обещания

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())))
}

лучший способ сделать это - реализовать фактический запрос Firestore в облачной функции? Тогда будет только один звонок в оба конца от клиента к Firebase, что, кажется, то, что вы просите.

В любом случае, вы действительно хотите сохранить всю логику доступа к данным, как на стороне сервера.

Внутренне, скорее всего, будет столько же вызовов самой Firebase, но все они будут проходить через сверхбыстрые соединения Google, а не во внешнюю сеть, и в сочетании с конвейерной обработкой, как объяснил Фрэнк ван Пуффелен, вы должны получить отличную производительность от этот подход.

 Jeremiah07 мар. 2018 г., 21:45
Хранение реализации в облачной функции является правильным решением в некоторых случаях, когда у вас сложная логика, но, вероятно, не в том случае, если вы просто хотите объединить список с несколькими идентификаторами. То, что вы теряете, - это кэширование на стороне клиента и стандартизированное форматирование возврата от обычных вызовов. Это вызвало больше проблем с производительностью, чем в некоторых случаях в моих приложениях, когда я использовал этот подход.
Решение Вопроса

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])}`);
* });
*/
 Kamana Kisinga24 янв. 2019 г., 14:31
@NickFranceschina Достаточно справедливо Спасибо, хотя
 Nick Franceschina22 янв. 2019 г., 12:26
спасибо @KamanaKisinga - исправлено
 Nick Franceschina24 янв. 2019 г., 12:19
Я сожалею @KamanaKisinga ... Я почти год не делал ничего для Firebase и не могу помочь в это время (эй, смотри, я действительно опубликовал этот ответ сегодня год назад!)
 Horea06 мар. 2018 г., 18:32
Для любого, кто хочет вызвать этот метод с динамически генерируемым массивом ссылок на документы, вы можете сделать это следующим образом: firestore.getAll (... arrayOfReferences) .then ()
 Kamana Kisinga23 янв. 2019 г., 10:56
@NickFranceschina Знаете ли вы, как это можно использовать на ванильных библиотеках angularfire или firebase?

не использованиеPromise.all как ваш клиент, то должен ждать.all чтение, прежде чем продолжить.

Выполните итерации чтения и дайте им разрешиться независимо. На клиентской стороне это, вероятно, сводится к тому, что пользовательский интерфейс имеет несколько образов загрузчика прогресса, независимо разрешающих значения. Тем не менее, это лучше, чем заморозить весь клиент до.all чтение решает.

Поэтому немедленно выведите все синхронные результаты в представление, а затем предоставьте асинхронные результаты по мере их разрешения по отдельности. Это может показаться мелким различием, но если у вашего клиента плохое подключение к Интернету (как у меня сейчас в этой кофейне), замораживание всего клиентского опыта на несколько секунд, скорее всего, приведет к тому, что это приложение отстой.

 Ryan Taylor08 мар. 2019 г., 20:12
Это асинхронный, есть много вариантов использования дляPromise.all... это не обязательно должно что-то "замораживать" - возможно, вам придется подождать все данные, прежде чем вы сможете сделать что-то значимое

маю, почему ответ Александра принимается, решение, которое он предлагает, просто возвращает все документы из коллекции «пользователей».

В зависимости от того, что вам нужно сделать, вам следует продублировать дубликаты соответствующих данных, которые необходимо отобразить, и запрашивать полный документ только при необходимости.

Вы можете использовать такую ​​функцию:

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

Его можно вызвать с одним идентификатором:

getById('collection', 'some_id')

или массив идентификаторов:

getById('collection', ['some_id', 'some_other_id'])

сейчас нет способа пакетировать несколько запросов на чтение с помощью Cloud Firestore SDK и, следовательно, нет способа гарантировать, что вы сможете прочитать все данные одновременно.

Однако, как сказал Фрэнк ван Пуффелен в комментариях выше, это не означает, что загрузка 3 документов будет в 3 раза медленнее, чем загрузка одного документа. Лучше выполнить свои собственные измерения, прежде чем прийти к заключению здесь.

 Sam Stern17 окт. 2017 г., 17:08
@ Кажется, вам придется пересмотреть свои структуры данных, чтобы повысить производительность в базе данных NoSQL, такой как Cloud Firestore. Лучший совет, который я могу дать, это думать задом наперед. Подумайте о запросе, который вы хотели бы выполнить, и структурируйте свои данные так, чтобы вы могли их просто выразить. Все запросы в Cloud Firestore выполняются быстро.
 Joon17 окт. 2017 г., 04:09
Дело в том, что я хочу знать теоретические ограничения производительности Firestore, прежде чем переходить на Firestore. Я не хочу мигрировать, а потом понимаю, что этого недостаточно для моего варианта использования.
 Sitian Liu27 окт. 2017 г., 23:17
@FrankvanPuffelen Например, в mongoDb вы можете использовать ObjectId следующим образомstackoverflow.com/a/32264630/648851.
 Joon17 окт. 2017 г., 04:11
Для меня без пакетной поддержки это не хорошо. Поскольку большинство вызовов базы данных моего приложения сводятся к получению нескольких (часто сотен) документов с несколькими идентификаторами. Чтобы быть быстрым, эти звонки должны быть для меня пакетными.
 Tapas Mukherjee26 окт. 2017 г., 00:02
Привет, здесь также есть консидерация cose. Допустим, у меня есть список всех идентификаторов моего друга, число которых равно 500. Я могу получить список за 1 стоимость чтения, но для отображения их имени и photoURL мне потребуется 500 операций чтения.

Ваш ответ на вопрос