Zastanawiam się, czy możliwe jest pobranie wielu dokumentów według listy identyfikatorów w jednej podróży w obie strony (połączenie sieciowe) do Firestore.
104
Zastanawiam się, czy możliwe jest pobranie wielu dokumentów według listy identyfikatorów w jednej podróży w obie strony (połączenie sieciowe) do Firestore.
a
,b
,c
aby coś zrobić. Proszę o wszystkie trzy równolegle w osobnych wnioskach.a
trwa 100 ms,b
trwa 150 ms ic
trwa 3000 ms . W rezultacie muszę poczekać 3000 ms, aby wykonać zadanie. Będziemax
z nich. Bardziej ryzykowne będzie, gdy liczba dokumentów do pobrania jest duża. W zależności od stanu sieci, myślę, że może to stanowić problem.SELECT * FROM docs WHERE id IN (a,b,c)
zajęłoby jednak tyle samo czasu? Nie widzę różnicy, ponieważ połączenie jest ustanawiane raz, a reszta jest przez to przepuszczana. Czas (po początkowym nawiązaniu połączenia) to czas wczytywania wszystkich dokumentów + 1 podróż w obie strony, taki sam dla obu podejść. Jeśli u Ciebie zachowuje się inaczej, czy możesz udostępnić próbkę (jak w moim powiązanym pytaniu)?Odpowiedzi:
jeśli jesteś w Node:
https://github.com/googleapis/nodejs-firestore/blob/master/dev/src/index.ts#L701
Dotyczy to szczególnie zestawu SDK serwera
AKTUALIZACJA: „Cloud Firestore [sdk po stronie klienta] obsługuje teraz zapytania!”
https://firebase.googleblog.com/2019/11/cloud-firestore-now-supports-in-queries.html
myCollection.where(firestore.FieldPath.documentId(), 'in', ["123","456","789"])
źródło
firebase.firestore.FieldPath.documentId()
a nie'id'
Właśnie ogłosili tę funkcję, https://firebase.googleblog.com/2019/11/cloud-firestore-now-supports-in-queries.html .
Teraz możesz używać zapytań takich jak, ale pamiętaj, że rozmiar wejściowy nie może być większy niż 10.
userCollection.where('uid', 'in', ["1231","222","2131"])
źródło
db.collection('users').where(firebase.firestore.FieldPath.documentId(), 'in',["123","345","111"]).get()
firebase.firestore.FieldPath.documentId()
Nie, w tej chwili nie ma możliwości grupowania wielu żądań odczytu za pomocą pakietu SDK Cloud Firestore, a zatem nie ma możliwości zagwarantowania, że można odczytać wszystkie dane naraz.
Jednak, jak powiedział Frank van Puffelen w komentarzach powyżej, nie oznacza to, że pobranie 3 dokumentów będzie 3x wolniejsze niż pobranie jednego dokumentu. Najlepiej jest wykonać własne pomiary przed wyciągnięciem wniosków.
źródło
W praktyce użyłbyś firestore.getAll w ten sposób
lub ze składnią obietnicy
źródło
Możesz użyć takiej funkcji:
Można go wywołać za pomocą jednego identyfikatora:
lub tablica identyfikatorów:
źródło
Z pewnością najlepszym sposobem na to jest zaimplementowanie rzeczywistego zapytania Firestore w funkcji chmury? Byłoby wtedy tylko jedno połączenie w obie strony od klienta do Firebase, o które wydaje się, że właśnie o to prosisz.
Naprawdę chcesz i tak zachować całą logikę dostępu do danych, taką jak ta po stronie serwera.
Wewnętrznie prawdopodobnie będzie taka sama liczba połączeń z samym Firebase, ale wszystkie będą realizowane przez superszybkie połączenia międzysieciowe Google, a nie przez sieć zewnętrzną, aw połączeniu z potokami, które wyjaśnił Frank van Puffelen, powinieneś uzyskać doskonałą wydajność od to podejście.
źródło
Jeśli używasz trzepotania, możesz wykonać następujące czynności:
To zwróci Przyszłość,
List<DocumentSnapshot>
którą możesz iterować według własnego uznania.źródło
Oto jak zrobiłbyś coś takiego w Kotlin z Android SDK.
Może niekoniecznie odbywać się w jednej podróży w obie strony, ale skutecznie grupuje wynik i pozwala uniknąć wielu zagnieżdżonych wywołań zwrotnych.
Pamiętaj, że pobieranie określonych dokumentów jest znacznie lepsze niż pobieranie wszystkich dokumentów i filtrowanie wyników. Dzieje się tak, ponieważ Firestore pobiera opłaty za zestaw wyników zapytania.
źródło
Mam nadzieję, że to ci pomoże, działa na mnie.
źródło
W tej chwili nie wydaje się to możliwe w Firestore. Nie rozumiem, dlaczego odpowiedź Aleksandra została przyjęta, rozwiązanie, które proponuje, zwraca po prostu wszystkie dokumenty z kolekcji „użytkownicy”.
W zależności od tego, co musisz zrobić, powinieneś rozważyć powielenie odpowiednich danych, które chcesz wyświetlić, i zażądać pełnego dokumentu tylko wtedy, gdy jest to konieczne.
źródło
Najlepsze, co możesz zrobić, to nie używać go
Promise.all
jako klienta, a następnie musi czekać.all
odczyt przed kontynuowaniem.Powtarzaj odczyty i pozwól im rozwiązać się niezależnie. Po stronie klienta prawdopodobnie sprowadza się to do tego, że interfejs użytkownika ma kilka obrazów programu ładującego postęp, które są przetwarzane na wartości niezależnie. Jest to jednak lepsze niż zamrażanie całego klienta do
.all
czasu rozwiązania odczytów.Dlatego natychmiast zrzuć wszystkie synchroniczne wyniki do widoku, a następnie pozwól, aby asynchroniczne wyniki pojawiały się indywidualnie, gdy zostaną rozwiązane. Może się to wydawać drobnym rozróżnieniem, ale jeśli twój klient ma słabą łączność z Internetem (tak jak ja mam obecnie w tej kawiarni), zamrożenie całego doświadczenia klienta na kilka sekund prawdopodobnie spowoduje, że `` ta aplikacja jest do bani ''.
źródło
Promise.all
… niekoniecznie musi cokolwiek „zamrażać” - być może będziesz musiał poczekać na wszystkie dane, zanim będziesz w stanie zrobić coś znaczącego