Czy można policzyć, ile elementów ma kolekcja, korzystając z nowej bazy danych Firebase, Cloud Firestore?
Jeśli tak, jak mam to zrobić?
firebase
google-cloud-firestore
Guilherme Torres Castro
źródło
źródło
Odpowiedzi:
Aktualizacja (kwiecień 2019 r.) - FieldValue.increment (zobacz rozwiązanie dotyczące dużej kolekcji)
Jak w przypadku wielu pytań, odpowiedź brzmi - to zależy .
Należy być bardzo ostrożnym podczas obsługi dużych ilości danych w interfejsie użytkownika. Oprócz spowolnienia interfejsu, Firestore pobiera również opłatę w wysokości 0,60 USD za milion wykonanych odczytów .
Mała kolekcja (mniej niż 100 dokumentów)
Używaj ostrożnie - wrażenia użytkownika Frontend mogą się nie udać
Obsługa tego z przodu powinna wystarczyć, o ile nie wykonujesz zbyt dużej logiki z tą zwróconą tablicą.
Średni zbiór (od 100 do 1000 dokumentów)
Używaj ostrożnie - wywołania odczytu Firestore mogą dużo kosztować
Poradzenie sobie z tym z przodu nie jest wykonalne, ponieważ ma zbyt duży potencjał spowolnienia systemu użytkowników. Powinniśmy obsłużyć tę stronę serwera logiki i zwracać tylko rozmiar.
Wadą tej metody jest to, że nadal wywołujesz odczyty Firestore (równe rozmiarowi twojej kolekcji), co na dłuższą metę może Cię kosztować więcej niż oczekiwano.
Funkcja chmury:
Front End:
Duża kolekcja (ponad 1000 dokumentów)
Najbardziej skalowalne rozwiązanie
Od kwietnia 2019 roku Firestore umożliwia teraz zwiększanie liczników całkowicie atomowo i bez wcześniejszego odczytu danych . Zapewnia to prawidłowe wartości liczników nawet podczas jednoczesnej aktualizacji z wielu źródeł (wcześniej rozwiązanych za pomocą transakcji), jednocześnie zmniejszając liczbę odczytów bazy danych, które wykonujemy.
Słuchając usuniętych lub utworzonych dokumentów, możemy dodawać lub usuwać z pola licznika, które znajduje się w bazie danych.
Zapoznaj się z dokumentacją firestore - Distributed Counters lub zajrzyj do Data Aggregation autorstwa Jeffa Delaneya. Jego przewodniki są naprawdę fantastyczne dla każdego, kto używa AngularFire, ale jego lekcje powinny zostać przeniesione również na inne ramy.
Funkcja chmury:
Teraz w interfejsie możesz po prostu zapytać to pole numberOfDocs, aby uzyskać rozmiar kolekcji.
źródło
firestore.runTransaction { ... }
bloku. Rozwiązuje to problemy ze współbieżnością podczas uzyskiwania dostępunumberOfDocs
.Najprostszym sposobem jest odczytanie rozmiaru „querySnapshot”.
Możesz również odczytać długość tablicy docs w „querySnapshot”.
Lub jeśli „querySnapshot” jest puste, odczytując pustą wartość, która zwróci wartość logiczną.
źródło
db.collection.count()
. Myśląc o upuszczeniu ich tylko z tego powoduO ile wiem, nie ma na to wbudowanego rozwiązania i jest to obecnie możliwe tylko w węźle sdk. Jeśli masz
możesz użyć
aby zdefiniować, które pole chcesz zaznaczyć. Jeśli wykonasz puste polecenie select (), otrzymasz po prostu tablicę odwołań do dokumentów.
przykład:
db.collection('someCollection').select().get().then( (snapshot) => console.log(snapshot.docs.length) );
To rozwiązanie jest tylko optymalizacją dla najgorszego przypadku pobierania wszystkich dokumentów i nie skaluje się na duże zbiory!
Spójrz też na to:
jak uzyskać liczbę dokumentów w kolekcji za pomocą Cloud Firestore
źródło
select(['_id'])
wynika , że jest szybszy niżselect()
Uważaj, licząc dokumenty w przypadku dużych zbiorów . Jest to trochę skomplikowane z bazą danych Firestore, jeśli chcesz mieć wstępnie obliczony licznik dla każdej kolekcji.
Taki kod nie działa w tym przypadku:
Powodem jest to, że każdy wyzwalacz Cloud Firestore musi być idempotentny, jak mówi dokumentacja Firestore: https://firebase.google.com/docs/functions/firestore-events#limitations_and_guarantees
Rozwiązanie
Tak więc, aby zapobiec wielokrotnemu wykonywaniu kodu, musisz zarządzać zdarzeniami i transakcjami. Oto mój sposób obsługi dużych liczników kolekcji:
Zastosuj tutaj:
Jak widać, kluczem do zapobiegania wielokrotnemu wykonywaniu jest właściwość o nazwie eventId w obiekcie kontekstu. Jeśli funkcja była obsługiwana wiele razy dla tego samego zdarzenia, identyfikator zdarzenia będzie taki sam we wszystkich przypadkach. Niestety, musisz mieć kolekcję „wydarzeń” w swojej bazie danych.
źródło
context.eventId
zawsze będzie to samo w przypadku wielu wywołań tego samego wyzwalacza? W moich testach wydaje się być spójny, ale nie mogę znaleźć żadnej „oficjalnej” dokumentacji, która to potwierdza.W 2020 r. Nadal nie jest dostępny w pakiecie Firebase SDK, ale jest dostępny w rozszerzeniach Firebase (Beta), jednak konfiguracja i użytkowanie jest dość skomplikowane ...
Rozsądne podejście
Pomocnicy ... (tworzenie / usuwanie wydaje się zbędne, ale jest tańsze niż w przypadku aktualizacji)
Wyeksportowane hooki Firestore
W akcji
Śledzona będzie główna kolekcja budynku i wszystkie kolekcje podrzędne .
Tutaj pod
/counters/
ścieżką głównąTeraz liczniki kolekcji będą aktualizowane automatycznie i ostatecznie! Jeśli potrzebujesz licznika, po prostu użyj ścieżki kolekcji i poprzedz ją prefiksem
counters
.źródło
Zgadzam się z @Matthew, wykonanie takiego zapytania będzie sporo kosztować .
[PORADY DLA PROGRAMISTÓW PRZED ROZPOCZĘCIEM PROJEKTÓW]
Ponieważ przewidzieliśmy taką sytuację na początku, możemy faktycznie stworzyć kolekcję, a mianowicie liczniki z dokumentem do przechowywania wszystkich liczników w polu z typem
number
.Na przykład:
Dla każdej operacji CRUD w kolekcji zaktualizuj dokument licznika:
Następnym razem, gdy chcesz uzyskać numer kolekcji, wystarczy wysłać zapytanie / wskazać pole dokumentu. [1 operacja odczytu]
Ponadto możesz przechowywać nazwę kolekcji w tablicy, ale będzie to trudne, stan tablicy w firebase jest pokazany poniżej:
Tak więc, jeśli nie zamierzasz usuwać kolekcji, możesz faktycznie użyć tablicy do przechowywania listy nazw kolekcji, zamiast sprawdzać całą kolekcję za każdym razem.
Mam nadzieję, że to pomoże!
źródło
Nie, obecnie nie ma wbudowanej obsługi zapytań agregujących. Jest jednak kilka rzeczy, które możesz zrobić.
Pierwsza jest udokumentowana tutaj . Możesz używać transakcji lub funkcji chmury do przechowywania informacji zbiorczych:
Ten przykład pokazuje, jak używać funkcji do śledzenia liczby ocen w podkolekcji, a także średniej oceny.
Rozwiązanie, o którym wspomniał jbb, jest również przydatne, jeśli chcesz rzadko zliczać dokumenty. Upewnij się, że używasz
select()
instrukcji, aby uniknąć pobierania całego każdego dokumentu (to dużo przepustowości, gdy potrzebujesz tylko liczby).select()
jest obecnie dostępne tylko w pakietach SDK serwera, więc rozwiązanie nie będzie działać w aplikacji mobilnej.źródło
Nie ma dostępnej opcji bezpośredniej. Nie możesz tego zrobić
db.collection("CollectionName").count()
. Poniżej znajdują się dwa sposoby, za pomocą których można znaleźć liczbę dokumentów w kolekcji.1: - Zbierz wszystkie dokumenty w kolekcji, a następnie sprawdź ich rozmiar. (Nie jest to najlepsze rozwiązanie)
Używając powyższego kodu, odczytany dokument będzie równy rozmiarowi dokumentów w kolekcji, dlatego należy unikać stosowania powyższego rozwiązania.
2: - Utwórz osobny dokument w swojej kolekcji, który będzie przechowywać liczbę dokumentów w kolekcji. (Najlepsze rozwiązanie)
Powyżej stworzyliśmy dokument z licznikami nazw, aby przechowywać wszystkie informacje o licznikach.Możesz zaktualizować dokument liczenia w następujący sposób: -
cena wrt (odczyt dokumentu = 1) i szybkie pobieranie danych powyższe rozwiązanie jest dobre.
źródło
Zwiększ licznik za pomocą admin.firestore.FieldValue.increment :
W tym przykładzie zwiększamy
instanceCount
pole w projekcie za każdym razem, gdy dokument jest dodawany doinstances
kolekcji podrzędnej. Jeśli pole jeszcze nie istnieje, zostanie utworzone i zwiększone do 1.Przyrost jest wewnętrznie transakcyjny, ale jeśli chcesz zwiększać częściej niż co 1 sekundę , powinieneś używać licznika rozproszonego .
Często lepiej jest wdrożyć
onCreate
ionDelete
zamiastonWrite
wzywaćonWrite
aktualizacje, co oznacza, że wydajesz więcej pieniędzy na niepotrzebne wywołania funkcji (jeśli aktualizujesz dokumenty w swojej kolekcji).źródło
Sposób obejścia:
napisz licznik w dokumencie Firebase, który zwiększasz w ramach transakcji za każdym razem, gdy tworzysz nowy wpis
Liczbę zapisujesz w polu nowego wpisu (np. Pozycja: 4).
Następnie tworzysz indeks na tym polu (pozycja DESC).
Możesz ustawić pomiń + limit za pomocą zapytania. Gdzie ("pozycja", "<" x) .OrderBy ("pozycja", DESC)
Mam nadzieję że to pomoże!
źródło
Stworzyłem uniwersalną funkcję, wykorzystując wszystkie te pomysły do obsługi wszystkich przeciwnych sytuacji (z wyjątkiem zapytań).
Obsługuje zdarzenia, przyrosty i transakcje. Piękno w tym polega na tym, że jeśli nie jesteś pewien dokładności dokumentu (prawdopodobnie będąc jeszcze w wersji beta), możesz usunąć licznik, aby automatycznie dodawał je przy następnym wyzwalaczu. Tak, to kosztuje, więc nie usuwaj go inaczej.
Ten sam rodzaj rzeczy, aby obliczyć:
Możesz również utworzyć zadanie cron (funkcja zaplanowana), aby usunąć stare zdarzenia, aby zaoszczędzić pieniądze na przechowywaniu bazy danych. Potrzebujesz przynajmniej planu blaze i może być więcej konfiguracji. Na przykład można go uruchamiać w każdą niedzielę o 23:00. https://firebase.google.com/docs/functions/schedule-functions
To nie jest testowane , ale powinno działać z kilkoma poprawkami:
I wreszcie, nie zapomnij zabezpieczyć kolekcji w firestore.rules :
Aktualizacja: zapytania
Dodając do mojej drugiej odpowiedzi, jeśli chcesz również zautomatyzować liczbę zapytań, możesz użyć tego zmodyfikowanego kodu w swojej funkcji chmury:
Który automatycznie zaktualizuje postsCount w userDocument. W ten sposób możesz łatwo dodać kolejny do wielu obliczeń. To tylko daje pomysły na zautomatyzowanie rzeczy. Podałem ci również inny sposób usuwania wydarzeń. Musisz przeczytać każdą datę, aby ją usunąć, więc tak naprawdę nie zaoszczędzi ci to późniejszego usunięcia, po prostu spowalnia funkcję.
źródło
Zajęło mi trochę czasu, zanim to działało w oparciu o niektóre z powyższych odpowiedzi, więc pomyślałem, że podzielę się nim z innymi. Mam nadzieję, że to przydatne.
źródło
Wiele próbowałem z różnymi podejściami. I na koniec doskonalę jedną z metod. Najpierw musisz utworzyć osobną kolekcję i zapisać tam wszystkie wydarzenia. Po drugie, musisz stworzyć nową lambdę, która będzie wyzwalana przez czas. Ta lambda zlicza zdarzenia w kolekcji zdarzeń i czyści dokumenty zdarzeń. Szczegóły kodu w artykule. https://medium.com/@ihor.malaniuk/how-to-count-documents-in-google-cloud-firestore-b0e65863aeca
źródło
To zapytanie zwróci liczbę dokumentów.
źródło
Wykorzystuje liczenie do tworzenia numerycznego unikalnego identyfikatora. W moim użyciu nigdy nie będę dekrementował , nawet jeśli
document
identyfikator jest potrzebny, zostanie usunięty.Na
collection
stworzenie, które wymaga unikalnej wartości liczbowejappData
jednym dokumentemset
o.doc
identyfikatorzeonly
uniqueNumericIDAmount
na 0 wfirebase firestore console
doc.data().uniqueNumericIDAmount + 1
jako unikalnego identyfikatora numerycznegoappData
kolekcję zauniqueNumericIDAmount
pomocąfirebase.firestore.FieldValue.increment(1)
źródło
źródło