Обходной путь для ограничения firebase «IN» в 10, совместимого с onSnapshot?

Я столкнулся с ограничением firebase «IN», равным 10. Хотя обходное решение уже было дано здесь:

Есть ли обходной путь для ограничения «IN» запросов Firebase до 10?

Ни одно из решений в этом потоке не работает с прослушивателем «onSnapshot». Для моего варианта использования (Vue 3) у меня есть составной/функциональный вызов I, который запрашивает передачу firebase в массив, который может иметь до 100 значений идентификатора документа, и возвращает объект, как показано ниже.

Это возможно?

import { ref, watchEffect } from 'vue'
import { db } from '@/firebase/config'
import { collection, onSnapshot, query, where, documentId } from 'firebase/firestore'

const getUsersList = (idList) => { 
    // idList is an array of document ID's
    const documents = ref(null)
    let collectionRef = collection(db, 'users')
    collectionRef = query(collectionRef, where(documentId(), 'in', idList))
    // this fails if I pass in more than 10 elements in the array
    const unsub = onSnapshot(collectionRef, snapshot => {
        let results = []
        snapshot.docs.forEach(doc => {
            results.push({ ...doc.data(), id: doc.id })
        })
        // update values
        documents.value = results
    })
    watchEffect((onInvalidate) => {
        onInvalidate(() => unsub())
    })
    return { documents }
}

export default getCollectionRt

Вам действительно следует вообще отказаться от использования «in» и просто настроить прослушиватели для каждого отдельного документа. При этом нет реальных затрат или снижения производительности, и это упростит ваш код. Если у вас есть какие-то особые требования к использованию «in», вы должны указать это в своем вопросе. В противном случае ваш вопрос на самом деле ничем не отличается от оригинала, на который вы ссылались, - это точно такая же проблема с теми же решениями, которые используют прослушиватели вместо прямого потребления результатов.

Doug Stevenson 06.02.2023 21:20

Я был бы согласен с этим, но не могли бы вы показать пример с несколькими слушателями, которые возвращают один объект, содержащий результаты всех из них, как было задано?

BGMX 07.02.2023 12:41

Зачем вообще нужны слушатели, если нужен только один результат? Если это все, что вам нужно, просто get() каждый документ отдельно.

Doug Stevenson 07.02.2023 14:17

Мне нужен один результат, который обновляется, если базовые данные обновляются, следовательно, используется onSnapshot и тема этого поста.

BGMX 08.02.2023 00:34

Потребуется много работы, чтобы собрать это вместе, независимо от того, используете ли вы несколько «входящих» запросов или отдельные прослушиватели документов. Не будет единого прослушивателя запросов, который может делать все это.

Doug Stevenson 08.02.2023 01:49

Правильно, «... массив, который может иметь до 100 значений идентификатора документа», я бы предположил, что потребуется до 10 слушателей.

BGMX 08.02.2023 13:06
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
6
54
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вам нужно будет инициализировать несколько слушателей, то есть такое же количество запросов, но с onSnapshot() (может быть лучше, чем настраивать прослушиватель для каждого отдельного документа). Пытаться:

import { ref } from 'vue';
import { collection, query, where, documentId, onSnapshot } from 'firebase/firestore'

const users = ref({})
const dataLoaded = ref(false)

const addFirestoreListeners = async () => {
  const idList = [];

  for (let i = 0; i < idList.length; i += 10) {
    const items = idList.slice(i, i + 10)

    const q = query(collection(db, 'users'), where(documentId(), 'in', items))

    onSnapshot(q, (snapshot) => {
      if (dataLoaded.value) {
        snapshot.docChanges().forEach((change) => {
          if (change.type === 'added' || change.type === 'modified') {
            users.value[change.doc.id] = change.doc.data()
          } else (change.type === 'removed') {
            users.value[change.doc.id] = null
          }
        })
      } else {
        snapshot.forEach((doc) => {
          users.value[doc.id] = doc.data()
        })

        dataLoaded.value = true
      }
    })
  }
}

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

@BGMX мой код продолжает обновлять один и тот же объект каждый раз, когда слушатель получает обновление. Вы можете использовать Object.values(users) для отображения данных в пользовательском интерфейсе. Что Вы ищете?

Dharmaraj 07.02.2023 12:43

Будет ли субъект работать так же, как оригинал, даже с несколькими слушателями, или соединение сохранится?

BGMX 07.02.2023 12:53
Ответ принят как подходящий

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

import { ref, watchEffect } from 'vue'
import { db } from '@/firebase/config'
import { collection, onSnapshot, query, where, documentId } from 'firebase/firestore'


const getUserList = (idList) => {
    console.info('idList', idList)
    let documents = ref(null)
    let collectionRef = collection(db, 'users')

    let unsub, unsubes = [], resultsList = [{}];
    for (let i = 0; i < idList.length; i += 10) {
        let idList1 = idList.slice(i, i + 10); //console.info(idList1);
        let collectionRef1 = query(collectionRef, where(documentId(), 'in', idList1))
        unsub = onSnapshot(collectionRef1, snapshot => {
            let results = []
            snapshot.docs.forEach(doc => {
                results.push({ ...doc.data(), id: doc.id })
            })
            resultsList.splice(resultsList.length, 0, ...results);
            console.info('results', results)
            documents.value = results
        })
        unsubes.push(unsub);
    }
    watchEffect((onInvalidate) => {
        onInvalidate(() =>{ unsubes.forEach(unsub => { unsub();         console.info("unsut", unsub); }) });       
    })
    Promise.all(unsubes);
    resultsList.shift(0);
    console.info("docu", documents.value);
    return { documents };
}

export default getUserList

Другие вопросы по теме