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ć?
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ć?
Odpowiedzi:
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 .
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ą.
db.collection('...').get().then(snap => {
size = snap.size // will return the collection size
});
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:
...
db.collection('...').get().then(snap => {
res.status(200).send({length: snap.size});
});
Front End:
yourHttpClient.post(yourCloudFunctionUrl).toPromise().then(snap => {
size = snap.length // will return the collection size
})
Najbardziej skalowalne rozwiązanie
FieldValue.increment ()
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:
export const documentWriteListener =
functions.firestore.document('collection/{documentUid}')
.onWrite((change, context) => {
if (!change.before.exists) {
// New document Created : add one to count
db.doc(docRef).update({numberOfDocs: FieldValue.increment(1)});
} else if (change.before.exists && change.after.exists) {
// Updating existing document : Do nothing
} else if (!change.after.exists) {
// Deleting document : subtract one from count
db.doc(docRef).update({numberOfDocs: FieldValue.increment(-1)});
}
return;
});
Teraz w interfejsie możesz po prostu zapytać to pole numberOfDocs, aby uzyskać rozmiar kolekcji.
firestore.runTransaction { ... }
bloku. Rozwiązuje to problemy ze współbieżnością podczas uzyskiwania dostępu numberOfDocs
.
Najprostszym sposobem jest odczytanie rozmiaru „querySnapshot”.
db.collection("cities").get().then(function(querySnapshot) {
console.log(querySnapshot.size);
});
Możesz również odczytać długość tablicy docs w „querySnapshot”.
querySnapshot.docs.length;
Lub jeśli „querySnapshot” jest puste, odczytując pustą wartość, która zwróci wartość logiczną.
querySnapshot.empty;
db.collection.count()
. Myśląc o upuszczeniu ich tylko z tego powodu
O ile wiem, nie ma na to wbudowanego rozwiązania i jest to obecnie możliwe tylko w węźle sdk. Jeśli masz
db.collection('someCollection')
możesz użyć
.select([fields])
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
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:
export const customerCounterListener =
functions.firestore.document('customers/{customerId}')
.onWrite((change, context) => {
// on create
if (!change.before.exists && change.after.exists) {
return firestore
.collection('metadatas')
.doc('customers')
.get()
.then(docSnap =>
docSnap.ref.set({
count: docSnap.data().count + 1
}))
// on delete
} else if (change.before.exists && !change.after.exists) {
return firestore
.collection('metadatas')
.doc('customers')
.get()
.then(docSnap =>
docSnap.ref.set({
count: docSnap.data().count - 1
}))
}
return null;
});
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
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:
const executeOnce = (change, context, task) => {
const eventRef = firestore.collection('events').doc(context.eventId);
return firestore.runTransaction(t =>
t
.get(eventRef)
.then(docSnap => (docSnap.exists ? null : task(t)))
.then(() => t.set(eventRef, { processed: true }))
);
};
const documentCounter = collectionName => (change, context) =>
executeOnce(change, context, t => {
// on create
if (!change.before.exists && change.after.exists) {
return t
.get(firestore.collection('metadatas')
.doc(collectionName))
.then(docSnap =>
t.set(docSnap.ref, {
count: ((docSnap.data() && docSnap.data().count) || 0) + 1
}));
// on delete
} else if (change.before.exists && !change.after.exists) {
return t
.get(firestore.collection('metadatas')
.doc(collectionName))
.then(docSnap =>
t.set(docSnap.ref, {
count: docSnap.data().count - 1
}));
}
return null;
});
Zastosuj tutaj:
/**
* Count documents in articles collection.
*/
exports.articlesCounter = functions.firestore
.document('articles/{id}')
.onWrite(documentCounter('articles'));
/**
* Count documents in customers collection.
*/
exports.customersCounter = functions.firestore
.document('customers/{id}')
.onWrite(documentCounter('customers'));
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.
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)
export const onCreateCounter = () => async (
change,
context
) => {
const collectionPath = change.ref.parent.path;
const statsDoc = db.doc("counters/" + collectionPath);
const countDoc = {};
countDoc["count"] = admin.firestore.FieldValue.increment(1);
await statsDoc.set(countDoc, { merge: true });
};
export const onDeleteCounter = () => async (
change,
context
) => {
const collectionPath = change.ref.parent.path;
const statsDoc = db.doc("counters/" + collectionPath);
const countDoc = {};
countDoc["count"] = admin.firestore.FieldValue.increment(-1);
await statsDoc.set(countDoc, { merge: true });
};
export interface CounterPath {
watch: string;
name: string;
}
Wyeksportowane hooki Firestore
export const Counters: CounterPath[] = [
{
name: "count_buildings",
watch: "buildings/{id2}"
},
{
name: "count_buildings_subcollections",
watch: "buildings/{id2}/{id3}/{id4}"
}
];
Counters.forEach(item => {
exports[item.name + '_create'] = functions.firestore
.document(item.watch)
.onCreate(onCreateCounter());
exports[item.name + '_delete'] = functions.firestore
.document(item.watch)
.onDelete(onDeleteCounter());
});
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
.
const collectionPath = 'buildings/138faicnjasjoa89/buildingContacts';
const collectionCount = await db
.doc('counters/' + collectionPath)
.get()
.then(snap => snap.get('count'));
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:
// we send this
['a', 'b', 'c', 'd', 'e']
// Firebase stores this
{0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e'}
// since the keys are numeric and sequential,
// if we query the data, we get this
['a', 'b', 'c', 'd', 'e']
// however, if we then delete a, b, and d,
// they are no longer mostly sequential, so
// we do not get back an array
{2: 'c', 4: 'e'}
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!
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.
exports.aggregateRatings = firestore
.document('restaurants/{restId}/ratings/{ratingId}')
.onWrite(event => {
// Get value of the newly added rating
var ratingVal = event.data.get('rating');
// Get a reference to the restaurant
var restRef = db.collection('restaurants').document(event.params.restId);
// Update aggregations in a transaction
return db.transaction(transaction => {
return transaction.get(restRef).then(restDoc => {
// Compute new number of ratings
var newNumRatings = restDoc.data('numRatings') + 1;
// Compute new average rating
var oldRatingTotal = restDoc.data('avgRating') * restDoc.data('numRatings');
var newAvgRating = (oldRatingTotal + ratingVal) / newNumRatings;
// Update restaurant info
return transaction.update(restRef, {
avgRating: newAvgRating,
numRatings: newNumRatings
});
});
});
});
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.
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.
db.collection("CollectionName").get().subscribe(doc=>{
console.log(doc.size)
})
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.
db.collection("CollectionName").doc("counts")get().subscribe(doc=>{
console.log(doc.count)
})
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.
Zwiększ licznik za pomocą admin.firestore.FieldValue.increment :
exports.onInstanceCreate = functions.firestore.document('projects/{projectId}/instances/{instanceId}')
.onCreate((snap, context) =>
db.collection('projects').doc(context.params.projectId).update({
instanceCount: admin.firestore.FieldValue.increment(1),
})
);
exports.onInstanceDelete = functions.firestore.document('projects/{projectId}/instances/{instanceId}')
.onDelete((snap, context) =>
db.collection('projects').doc(context.params.projectId).update({
instanceCount: admin.firestore.FieldValue.increment(-1),
})
);
W tym przykładzie zwiększamy instanceCount
pole w projekcie za każdym razem, gdy dokument jest dodawany do instances
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
i onDelete
zamiast onWrite
wzywać onWrite
aktualizacje, co oznacza, że wydajesz więcej pieniędzy na niepotrzebne wywołania funkcji (jeśli aktualizujesz dokumenty w swojej kolekcji).
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!
Stworzyłem uniwersalną funkcję, wykorzystując wszystkie te pomysły do obsługi wszystkich przeciwnych sytuacji (z wyjątkiem zapytań).
Jedynym wyjątkiem byłoby, gdyby tak wiele zapisów na sekundę spowalniało. Przykładem może być polubienie postu zyskującego popularność. Na przykład jest to przesada w przypadku wpisu na blogu i będzie Cię kosztować więcej. Proponuję w takim przypadku stworzyć osobną funkcję za pomocą shardów: https://firebase.google.com/docs/firestore/solutions/counters
// trigger collections
exports.myFunction = functions.firestore
.document('{colId}/{docId}')
.onWrite(async (change: any, context: any) => {
return runCounter(change, context);
});
// trigger sub-collections
exports.mySubFunction = functions.firestore
.document('{colId}/{docId}/{subColId}/{subDocId}')
.onWrite(async (change: any, context: any) => {
return runCounter(change, context);
});
// add change the count
const runCounter = async function (change: any, context: any) {
const col = context.params.colId;
const eventsDoc = '_events';
const countersDoc = '_counters';
// ignore helper collections
if (col.startsWith('_')) {
return null;
}
// simplify event types
const createDoc = change.after.exists && !change.before.exists;
const updateDoc = change.before.exists && change.after.exists;
if (updateDoc) {
return null;
}
// check for sub collection
const isSubCol = context.params.subDocId;
const parentDoc = `${countersDoc}/${context.params.colId}`;
const countDoc = isSubCol
? `${parentDoc}/${context.params.docId}/${context.params.subColId}`
: `${parentDoc}`;
// collection references
const countRef = db.doc(countDoc);
const countSnap = await countRef.get();
// increment size if doc exists
if (countSnap.exists) {
// createDoc or deleteDoc
const n = createDoc ? 1 : -1;
const i = admin.firestore.FieldValue.increment(n);
// create event for accurate increment
const eventRef = db.doc(`${eventsDoc}/${context.eventId}`);
return db.runTransaction(async (t: any): Promise<any> => {
const eventSnap = await t.get(eventRef);
// do nothing if event exists
if (eventSnap.exists) {
return null;
}
// add event and update size
await t.update(countRef, { count: i });
return t.set(eventRef, {
completed: admin.firestore.FieldValue.serverTimestamp()
});
}).catch((e: any) => {
console.log(e);
});
// otherwise count all docs in the collection and add size
} else {
const colRef = db.collection(change.after.ref.parent.path);
return db.runTransaction(async (t: any): Promise<any> => {
// update size
const colSnap = await t.get(colRef);
return t.set(countRef, { count: colSnap.size });
}).catch((e: any) => {
console.log(e);
});;
}
}
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ć:
const collectionPath = 'buildings/138faicnjasjoa89/buildingContacts';
const colSnap = await db.doc('_counters/' + collectionPath).get();
const count = colSnap.get('count');
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:
exports.scheduledFunctionCrontab = functions.pubsub.schedule('5 11 * * *')
.timeZone('America/New_York')
.onRun(async (context) => {
// get yesterday
const yesterday = new Date();
yesterday.setDate(yesterday.getDate() - 1);
const eventFilter = db.collection('_events').where('completed', '<=', yesterday);
const eventFilterSnap = await eventFilter.get();
eventFilterSnap.forEach(async (doc: any) => {
await doc.ref.delete();
});
return null;
});
I wreszcie, nie zapomnij zabezpieczyć kolekcji w firestore.rules :
match /_counters/{document} {
allow read;
allow write: if false;
}
match /_events/{document} {
allow read, write: if false;
}
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:
if (col === 'posts') {
// counter reference - user doc ref
const userRef = after ? after.userDoc : before.userDoc;
// query reference
const postsQuery = db.collection('posts').where('userDoc', "==", userRef);
// add the count - postsCount on userDoc
await addCount(change, context, postsQuery, userRef, 'postsCount');
}
return delEvents();
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ę.
/**
* Adds a counter to a doc
* @param change - change ref
* @param context - context ref
* @param queryRef - the query ref to count
* @param countRef - the counter document ref
* @param countName - the name of the counter on the counter document
*/
const addCount = async function (change: any, context: any,
queryRef: any, countRef: any, countName: string) {
// events collection
const eventsDoc = '_events';
// simplify event type
const createDoc = change.after.exists && !change.before.exists;
// doc references
const countSnap = await countRef.get();
// increment size if field exists
if (countSnap.get(countName)) {
// createDoc or deleteDoc
const n = createDoc ? 1 : -1;
const i = admin.firestore.FieldValue.increment(n);
// create event for accurate increment
const eventRef = db.doc(`${eventsDoc}/${context.eventId}`);
return db.runTransaction(async (t: any): Promise<any> => {
const eventSnap = await t.get(eventRef);
// do nothing if event exists
if (eventSnap.exists) {
return null;
}
// add event and update size
await t.set(countRef, { [countName]: i }, { merge: true });
return t.set(eventRef, {
completed: admin.firestore.FieldValue.serverTimestamp()
});
}).catch((e: any) => {
console.log(e);
});
// otherwise count all docs in the collection and add size
} else {
return db.runTransaction(async (t: any): Promise<any> => {
// update size
const colSnap = await t.get(queryRef);
return t.set(countRef, { [countName]: colSnap.size }, { merge: true });
}).catch((e: any) => {
console.log(e);
});;
}
}
/**
* Deletes events over a day old
*/
const delEvents = async function () {
// get yesterday
const yesterday = new Date();
yesterday.setDate(yesterday.getDate() - 1);
const eventFilter = db.collection('_events').where('completed', '<=', yesterday);
const eventFilterSnap = await eventFilter.get();
eventFilterSnap.forEach(async (doc: any) => {
await doc.ref.delete();
});
return null;
}
Powinienem również ostrzec, że funkcje uniwersalne będą działać w każdym okresie wywołania onWrite. Tańsze może być uruchamianie tej funkcji tylko w instancjach onCreate i onDelete określonych kolekcji. Podobnie jak w przypadku bazy danych noSQL, z którego korzystamy, powtarzanie kodu i danych pozwala zaoszczędzić pieniądze.
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.
'use strict';
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
const db = admin.firestore();
exports.countDocumentsChange = functions.firestore.document('library/{categoryId}/documents/{documentId}').onWrite((change, context) => {
const categoryId = context.params.categoryId;
const categoryRef = db.collection('library').doc(categoryId)
let FieldValue = require('firebase-admin').firestore.FieldValue;
if (!change.before.exists) {
// new document created : add one to count
categoryRef.update({numberOfDocs: FieldValue.increment(1)});
console.log("%s numberOfDocs incremented by 1", categoryId);
} else if (change.before.exists && change.after.exists) {
// updating existing document : Do nothing
} else if (!change.after.exists) {
// deleting document : subtract one from count
categoryRef.update({numberOfDocs: FieldValue.increment(-1)});
console.log("%s numberOfDocs decremented by 1", categoryId);
}
return 0;
});
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
To zapytanie zwróci liczbę dokumentów.
this.db.collection(doc).get().subscribe((data) => {
count = data.docs.length;
});
console.log(count)
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 liczbowej
appData
jednym dokumentem set
o .doc
identyfikatorzeonly
uniqueNumericIDAmount
na 0 wfirebase firestore console
doc.data().uniqueNumericIDAmount + 1
jako unikalnego identyfikatora numerycznegoappData
kolekcję za uniqueNumericIDAmount
pomocąfirebase.firestore.FieldValue.increment(1)
firebase
.firestore()
.collection("appData")
.doc("only")
.get()
.then(doc => {
var foo = doc.data();
foo.id = doc.id;
// your collection that needs a unique ID
firebase
.firestore()
.collection("uniqueNumericIDs")
.doc(user.uid)// user id in my case
.set({// I use this in login, so this document doesn't
// exist yet, otherwise use update instead of set
phone: this.state.phone,// whatever else you need
uniqueNumericID: foo.uniqueNumericIDAmount + 1
})
.then(() => {
// upon success of new ID, increment uniqueNumericIDAmount
firebase
.firestore()
.collection("appData")
.doc("only")
.update({
uniqueNumericIDAmount: firebase.firestore.FieldValue.increment(
1
)
})
.catch(err => {
console.log(err);
});
})
.catch(err => {
console.log(err);
});
});
firebaseFirestore.collection("...").addSnapshotListener(new EventListener<QuerySnapshot>() {
@Override
public void onEvent(QuerySnapshot documentSnapshots, FirebaseFirestoreException e) {
int Counter = documentSnapshots.size();
}
});