Подтвердить что ты не робот

Google Firestore - как получить документ несколькими идентификаторами за один раз?

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

4b9b3361

Ответ 1

если вы находитесь в узле:

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])}');
* });
*/

Ответ 2

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

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

Ответ 3

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

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

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

getById('collection', 'some_id')

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

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

Ответ 4

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

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

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

Ответ 5

На практике вы бы использовали firestore.getAll, как это

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

Ответ 6

Вот как вы можете сделать что-то подобное в Kotlin с Android SDK.
Не обязательно быть в одном цикле, но это эффективно группирует результат и позволяет избежать многих вложенных обратных вызовов.

val userIds = listOf("123", "456")
val userTasks = userIds.map { firestore.document("users/${it!!}").get() }

Tasks.whenAllSuccess<DocumentSnapshot>(userTasks).addOnSuccessListener { documentList ->
    //Do what you need to with the document list
}

Обратите внимание, что выборка определенных документов намного лучше, чем выборка всех документов и фильтрация результата. Это потому, что Firestore взимает плату за набор результатов запроса.

Ответ 7

В настоящее время это не представляется возможным в Firestore. Я не понимаю, почему ответ Alexander принят, решение, которое он предлагает, просто возвращает все документы в коллекции "users".

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

Ответ 8

Лучшее, что вы можете сделать, - это не использовать Promise.all качестве клиента, после чего он должен ждать .all чтения, прежде чем продолжить.

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

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