Kann mit der neuen Firebase-Datenbank Cloud Firestore gezählt werden, wie viele Elemente eine Sammlung enthält?
Wenn ja, wie mache ich das?
Kann mit der neuen Firebase-Datenbank Cloud Firestore gezählt werden, wie viele Elemente eine Sammlung enthält?
Wenn ja, wie mache ich das?
Antworten:
Wie bei vielen Fragen lautet die Antwort: Es kommt darauf an .
Sie sollten beim Umgang mit großen Datenmengen im Frontend sehr vorsichtig sein. Firestore sorgt nicht nur dafür, dass sich Ihr Front-End träge anfühlt, sondern berechnet Ihnen auch 0,60 US-Dollar pro Million Lesevorgänge .
Vorsichtig verwenden - Die Benutzererfahrung im Frontend kann beeinträchtigt werden
Die Behandlung am Frontend sollte in Ordnung sein, solange Sie mit diesem zurückgegebenen Array nicht zu viel Logik betreiben.
db.collection('...').get().then(snap => {
size = snap.size // will return the collection size
});
Vorsichtig verwenden - Firestore-Leseaufrufe können viel kosten
Dies am Frontend zu handhaben ist nicht möglich, da es zu viel Potenzial hat, das Benutzersystem zu verlangsamen. Wir sollten diese Logikserverseite behandeln und nur die Größe zurückgeben.
Der Nachteil dieser Methode ist, dass Sie immer noch Firestore-Lesevorgänge aufrufen (entsprechend der Größe Ihrer Sammlung), was Sie auf lange Sicht mehr kosten kann als erwartet.
Cloud-Funktion:
...
db.collection('...').get().then(snap => {
res.status(200).send({length: snap.size});
});
Vorderes Ende:
yourHttpClient.post(yourCloudFunctionUrl).toPromise().then(snap => {
size = snap.length // will return the collection size
})
Skalierbarste Lösung
FieldValue.increment ()
Ab April 2019 ermöglicht Firestore jetzt das Inkrementieren von Zählern vollständig atomar und ohne vorheriges Lesen der Daten . Dies stellt sicher, dass wir auch bei gleichzeitiger Aktualisierung aus mehreren Quellen (zuvor mithilfe von Transaktionen gelöst) korrekte Zählerwerte haben, und reduziert gleichzeitig die Anzahl der von uns durchgeführten Datenbanklesevorgänge.
Durch Abhören von gelöschten oder erstellten Dokumenten können wir ein Zählfeld in der Datenbank ergänzen oder daraus entfernen.
Sehen Sie sich die Firestore-Dokumente an - Verteilte Zähler oder werfen Sie einen Blick auf Data Aggregation von Jeff Delaney. Seine Anleitungen sind wirklich fantastisch für alle, die AngularFire verwenden, aber seine Lektionen sollten sich auch auf andere Frameworks übertragen lassen.
Cloud-Funktion:
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;
});
Jetzt können Sie im Frontend einfach dieses Feld numberOfDocs abfragen, um die Größe der Sammlung zu ermitteln.
firestore.runTransaction { ... }
Block einschließen sollten. Dies behebt Parallelitätsprobleme beim Zugriff numberOfDocs
.
Am einfachsten ist es, die Größe eines "querySnapshot" zu lesen.
db.collection("cities").get().then(function(querySnapshot) {
console.log(querySnapshot.size);
});
Sie können auch die Länge des docs-Arrays in "querySnapshot" lesen.
querySnapshot.docs.length;
Oder wenn ein "querySnapshot" leer ist, lesen Sie den leeren Wert, der einen booleschen Wert zurückgibt.
querySnapshot.empty;
db.collection.count()
. Ich denke, sie nur dafür fallen zu lassen
Soweit ich weiß, gibt es dafür keine eingebaute Lösung und dies ist derzeit nur im Node SDK möglich. Wenn Sie eine haben
db.collection('someCollection')
Sie können verwenden
.select([fields])
um zu definieren, welches Feld Sie auswählen möchten. Wenn Sie ein leeres select () ausführen, erhalten Sie nur eine Reihe von Dokumentreferenzen.
Beispiel:
db.collection('someCollection').select().get().then(
(snapshot) => console.log(snapshot.docs.length)
);
Diese Lösung ist nur eine Optimierung für den schlimmsten Fall des Herunterladens aller Dokumente und lässt sich nicht auf große Sammlungen skalieren!
Schauen Sie sich auch Folgendes an:
So erhalten Sie mit Cloud Firestore die Anzahl der Dokumente in einer Sammlung
select(['_id'])
ist schneller alsselect()
Zählen Sie die Anzahl der Dokumente für große Sammlungen sorgfältig . Die Firestore-Datenbank ist etwas komplex, wenn Sie für jede Sammlung einen vorberechneten Zähler haben möchten.
Code wie dieser funktioniert in diesem Fall nicht:
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;
});
Der Grund dafür ist, dass jeder Cloud-Firestore-Trigger idempotent sein muss, wie in der Firestore-Dokumentation angegeben: https://firebase.google.com/docs/functions/firestore-events#limitations_and_guarantees
Um zu verhindern, dass Ihr Code mehrfach ausgeführt wird, müssen Sie Ereignisse und Transaktionen verwalten. Dies ist meine besondere Art, mit großen Sammlungszählern umzugehen:
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;
});
Anwendungsfälle hier:
/**
* 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'));
Wie Sie sehen, ist der Schlüssel zum Verhindern der Mehrfachausführung die Eigenschaft eventId im Kontextobjekt . Wenn die Funktion für dasselbe Ereignis mehrmals ausgeführt wurde, ist die Ereignis-ID in allen Fällen dieselbe. Leider müssen Sie "Ereignissammlung" in Ihrer Datenbank haben.
context.eventId
dies bei mehreren Aufrufen desselben Triggers immer gleich ist? In meinen Tests scheint es konsistent zu sein, aber ich kann keine "offizielle" Dokumentation finden, die dies besagt.
Im Jahr 2020 ist dies im Firebase SDK noch nicht verfügbar, es ist jedoch in Firebase Extensions (Beta) verfügbar, es ist jedoch ziemlich komplex einzurichten und zu verwenden ...
Ein vernünftiger Ansatz
Helfer ... (Erstellen / Löschen scheint überflüssig, ist aber billiger als onUpdate)
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;
}
Exportierte Firestore-Hooks
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());
});
In Aktion
Die Gebäude Stammsammlung und alle Teilsammlungen werden verfolgt.
Hier unter dem /counters/
Wurzelpfad
Jetzt werden die Sammlungszahlen automatisch und eventuell aktualisiert! Wenn Sie eine Zählung benötigen, verwenden Sie einfach den Erfassungspfad und stellen Sie ihm ein Präfix voran counters
.
const collectionPath = 'buildings/138faicnjasjoa89/buildingContacts';
const collectionCount = await db
.doc('counters/' + collectionPath)
.get()
.then(snap => snap.get('count'));
Ich stimme @Matthew zu, es wird viel kosten, wenn Sie eine solche Abfrage durchführen.
[HINWEIS FÜR ENTWICKLER VOR BEGINN IHRER PROJEKTE]
Da wir diese Situation zu Beginn vorausgesehen haben, können wir tatsächlich eine Sammlung erstellen, nämlich Zähler mit einem Dokument, um alle Zähler in einem Feld mit Typ zu speichern number
.
Beispielsweise:
Aktualisieren Sie für jede CRUD-Operation in der Sammlung das Zählerdokument:
Wenn Sie das nächste Mal die Anzahl der Sammlungen abrufen möchten, müssen Sie nur das Dokumentfeld abfragen / darauf verweisen. [1 Lesevorgang]
Darüber hinaus können Sie den Sammlungsnamen in einem Array speichern. Dies ist jedoch schwierig. Der Zustand des Arrays in der Firebase wird wie folgt angezeigt:
// 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'}
Wenn Sie die Sammlung also nicht löschen möchten, können Sie das Array verwenden, um die Liste der Sammlungsnamen zu speichern, anstatt jedes Mal die gesamte Sammlung abzufragen.
Ich hoffe es hilft!
Nein, derzeit gibt es keine integrierte Unterstützung für Aggregationsabfragen. Es gibt jedoch einige Dinge, die Sie tun könnten.
Der erste ist hier dokumentiert . Sie können Transaktionen oder Cloud-Funktionen verwenden, um aggregierte Informationen zu verwalten:
Dieses Beispiel zeigt, wie Sie mithilfe einer Funktion die Anzahl der Bewertungen in einer Untersammlung sowie die durchschnittliche Bewertung verfolgen.
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
});
});
});
});
Die von jbb erwähnte Lösung ist auch nützlich, wenn Sie Dokumente nur selten zählen möchten. Stellen Sie sicher, dass Sie die select()
Anweisung verwenden, um zu vermeiden, dass alle Dokumente heruntergeladen werden (das ist viel Bandbreite, wenn Sie nur eine Zählung benötigen). select()
ist derzeit nur in den Server-SDKs verfügbar, sodass die Lösung in einer mobilen App nicht funktioniert.
Es ist keine direkte Option verfügbar. Das kannst du nicht db.collection("CollectionName").count()
. Im Folgenden finden Sie zwei Möglichkeiten, wie Sie die Anzahl der Dokumente in einer Sammlung ermitteln können.
db.collection("CollectionName").get().subscribe(doc=>{
console.log(doc.size)
})
Wenn Sie den obigen Code verwenden, entsprechen Ihre gelesenen Dokumente der Größe der Dokumente innerhalb einer Sammlung. Aus diesem Grund muss die Verwendung der obigen Lösung vermieden werden.
db.collection("CollectionName").doc("counts")get().subscribe(doc=>{
console.log(doc.count)
})
Oben haben wir ein Dokument mit Namenszählungen erstellt, um alle Zählinformationen zu speichern. Sie können das Zählungsdokument folgendermaßen aktualisieren: -
Für den Preis (Document Read = 1) und den schnellen Datenabruf ist die obige Lösung gut.
Inkrementieren Sie einen Zähler mit 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),
})
);
In diesem Beispiel erhöhen wir instanceCount
jedes Mal ein Feld im Projekt, wenn ein Dokument zur Untersammlung hinzugefügt wird instances
. Wenn das Feld noch nicht vorhanden ist, wird es erstellt und auf 1 erhöht.
Die Inkrementierung erfolgt intern, Sie sollten jedoch einen verteilten Zähler verwenden, wenn Sie häufiger als alle 1 Sekunde inkrementieren müssen.
Es ist oft vorzuziehen , zu implementieren onCreate
und onDelete
nicht , onWrite
wie Sie rufen onWrite
nach Updates , die bedeuten , dass Sie mehr Geld für unnötige Funktionsaufrufe ausgeben (wenn Sie die Dokumentation in Ihrer Sammlung aktualisieren).
Eine Problemumgehung ist:
Schreiben Sie einen Zähler in ein Firebase-Dokument, den Sie bei jeder Erstellung eines neuen Eintrags innerhalb einer Transaktion erhöhen
Sie speichern die Zählung in einem Feld Ihres neuen Eintrags (dh: Position: 4).
Anschließend erstellen Sie einen Index für dieses Feld (Position DESC).
Sie können mit einer Abfrage ein Überspringen + Limit durchführen. Wo ("Position", "<" x) .OrderBy ("Position", DESC)
Hoffe das hilft!
Mit all diesen Ideen habe ich eine universelle Funktion erstellt, um alle Gegensituationen (außer Abfragen) zu behandeln.
Die einzige Ausnahme wäre, wenn Sie so viele Schreibvorgänge pro Sekunde ausführen, dass Sie dadurch langsamer werden. Ein Beispiel wäre Likes auf einem Trendpost. Es ist zum Beispiel in einem Blog-Beitrag übertrieben und kostet Sie mehr. Ich schlage vor, in diesem Fall eine separate Funktion mit Shards zu erstellen: 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);
});;
}
}
Dies behandelt Ereignisse, Inkremente und Transaktionen. Das Schöne daran ist, dass Sie den Zähler löschen können, wenn Sie sich über die Genauigkeit eines Dokuments nicht sicher sind (wahrscheinlich noch in der Beta-Phase), damit es beim nächsten Auslöser automatisch addiert wird. Ja, das kostet, also löschen Sie es nicht anders.
Das Gleiche, um die Zählung zu erhalten:
const collectionPath = 'buildings/138faicnjasjoa89/buildingContacts';
const colSnap = await db.doc('_counters/' + collectionPath).get();
const count = colSnap.get('count');
Möglicherweise möchten Sie auch einen Cron-Job (geplante Funktion) erstellen, um alte Ereignisse zu entfernen und Geld beim Datenbankspeicher zu sparen. Sie benötigen mindestens einen Blaze-Plan, und möglicherweise ist eine weitere Konfiguration vorhanden. Sie könnten es zum Beispiel jeden Sonntag um 23 Uhr laufen lassen. https://firebase.google.com/docs/functions/schedule-functions
Dies ist nicht getestet , sollte aber mit ein paar Verbesserungen funktionieren:
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;
});
Und vergessen Sie nicht, die Sammlungen in firestore.rules zu schützen :
match /_counters/{document} {
allow read;
allow write: if false;
}
match /_events/{document} {
allow read, write: if false;
}
Update: Abfragen
Wenn Sie meiner anderen Antwort hinzufügen möchten, dass Sie auch die Anzahl der Abfragen automatisieren möchten, können Sie diesen geänderten Code in Ihrer Cloud-Funktion verwenden:
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();
Dadurch wird der postsCount im userDocument automatisch aktualisiert . Auf diese Weise können Sie leicht eine andere zu vielen Zählungen hinzufügen. Dies gibt Ihnen nur Ideen, wie Sie Dinge automatisieren können. Ich habe Ihnen auch eine andere Möglichkeit gegeben, die Ereignisse zu löschen. Sie müssen jedes Datum lesen, um es zu löschen, damit Sie es nicht wirklich speichern, um es später zu löschen. Dies verlangsamt nur die Funktion.
/**
* 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;
}
Ich sollte Sie auch warnen, dass universelle Funktionen in jeder onWrite-Aufrufperiode ausgeführt werden. Es ist möglicherweise billiger, die Funktion nur auf onCreate- und onDelete-Instanzen Ihrer spezifischen Sammlungen auszuführen. Wie bei der von uns verwendeten noSQL-Datenbank können Sie durch wiederholten Code und wiederholte Daten Geld sparen.
Ich habe eine Weile gebraucht, um dies basierend auf einigen der obigen Antworten zum Laufen zu bringen, also dachte ich, ich würde es für andere teilen. Ich hoffe es ist nützlich.
'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;
});
Ich habe viel mit verschiedenen Ansätzen versucht. Und schließlich verbessere ich eine der Methoden. Zuerst müssen Sie eine separate Sammlung erstellen und dort alle Ereignisse speichern. Zweitens müssen Sie ein neues Lambda erstellen, das durch die Zeit ausgelöst wird. Dieses Lambda zählt Ereignisse in der Ereignissammlung und löscht Ereignisdokumente. Codedetails im Artikel. https://medium.com/@ihor.malaniuk/how-to-count-documents-in-google-cloud-firestore-b0e65863aeca
Diese Abfrage führt zur Anzahl der Dokumente.
this.db.collection(doc).get().subscribe((data) => {
count = data.docs.length;
});
console.log(count)
firebaseFirestore.collection("...").addSnapshotListener(new EventListener<QuerySnapshot>() {
@Override
public void onEvent(QuerySnapshot documentSnapshots, FirebaseFirestoreException e) {
int Counter = documentSnapshots.size();
}
});