È possibile contare quanti elementi ha una raccolta utilizzando il nuovo database Firebase, Cloud Firestore?
In tal caso, come posso farlo?
È possibile contare quanti elementi ha una raccolta utilizzando il nuovo database Firebase, Cloud Firestore?
In tal caso, come posso farlo?
Risposte:
Come per molte domande, la risposta è: dipende .
Dovresti stare molto attento quando gestisci grandi quantità di dati sul front-end. Oltre a rendere lenta la tua parte frontale, Firestore ti addebita anche $ 0,60 per milione di letture che fai.
Usare con cura - L'esperienza dell'utente di Frontend potrebbe subire un colpo
Gestire questo sul front-end dovrebbe andare bene finché non si sta facendo troppa logica con questo array restituito.
db.collection('...').get().then(snap => {
size = snap.size // will return the collection size
});
Usare con cura: le invocazioni di lettura del Firestore possono costare molto
La gestione di questo front-end non è fattibile in quanto ha troppe potenzialità per rallentare il sistema degli utenti. Dovremmo gestire questo lato server logico e restituire solo le dimensioni.
Lo svantaggio di questo metodo è che stai ancora invocando le letture del deposito (pari alla dimensione della tua raccolta), che a lungo andare potrebbe finire per costarti più del previsto.
Funzione cloud:
...
db.collection('...').get().then(snap => {
res.status(200).send({length: snap.size});
});
Fine frontale:
yourHttpClient.post(yourCloudFunctionUrl).toPromise().then(snap => {
size = snap.length // will return the collection size
})
La soluzione più scalabile
FieldValue.increment ()
A partire da aprile 2019 Firestore ora consente di incrementare i contatori, in modo completamente atomico e senza leggere i dati prima . Ciò garantisce che abbiamo valori di contatore corretti anche durante l'aggiornamento da più origini contemporaneamente (precedentemente risolto utilizzando le transazioni), riducendo anche il numero di letture del database che eseguiamo.
Ascoltando qualsiasi documento eliminato o creato, possiamo aggiungere o rimuovere da un campo di conteggio presente nel database.
Guarda i documenti del Firestore - Distributed Counters o dai un'occhiata a Data Aggregation di Jeff Delaney. Le sue guide sono davvero fantastiche per chiunque utilizzi AngularFire, ma le sue lezioni dovrebbero ripercuotersi anche su altri framework.
Funzione cloud:
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;
});
Ora sul frontend puoi semplicemente interrogare questo campo numberOfDocs per ottenere le dimensioni della raccolta.
firestore.runTransaction { ... }
blocco. Questo risolve i problemi di concorrenza con l'accesso numberOfDocs
.
Il modo più semplice per farlo è leggere la dimensione di "querySnapshot".
db.collection("cities").get().then(function(querySnapshot) {
console.log(querySnapshot.size);
});
Puoi anche leggere la lunghezza dell'array di documenti all'interno di "querySnapshot".
querySnapshot.docs.length;
Oppure se un "querySnapshot" è vuoto leggendo il valore vuoto, che restituirà un valore booleano.
querySnapshot.empty;
db.collection.count()
. Pensando di lasciarli solo per questo
Per quanto ne so non esiste una soluzione integrata per questo ed è possibile solo nel nodo sdk in questo momento. Se hai un
db.collection('someCollection')
Puoi usare
.select([fields])
per definire quale campo si desidera selezionare. Se fai una selezione vuota () otterrai solo una serie di riferimenti a documenti.
esempio:
db.collection('someCollection').select().get().then(
(snapshot) => console.log(snapshot.docs.length)
);
Questa soluzione è solo un'ottimizzazione per il caso peggiore di scaricare tutti i documenti e non si adatta a grandi raccolte!
Dai un'occhiata anche a questo:
come ottenere un conteggio del numero di documenti in una raccolta con Cloud Firestore
select(['_id'])
è più veloce diselect()
Fai attenzione a contare il numero di documenti per raccolte di grandi dimensioni . È un po 'complesso con il database di firestore se si desidera avere un contatore precalcolato per ogni raccolta.
Codice come questo non funziona in questo caso:
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;
});
Il motivo è perché ogni trigger di cloud store deve essere idempotente, come dice la documentazione di fireestore: https://firebase.google.com/docs/functions/firestore-events#limitations_and_guarantees
Pertanto, al fine di prevenire più esecuzioni del codice, è necessario gestire eventi e transazioni. Questo è il mio modo particolare di gestire i contatori di raccolte di grandi dimensioni:
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;
});
Casi d'uso qui:
/**
* 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'));
Come puoi vedere, la chiave per impedire l'esecuzione multipla è la proprietà chiamata eventId nell'oggetto contesto. Se la funzione è stata gestita più volte per lo stesso evento, l'ID evento sarà lo stesso in tutti i casi. Sfortunatamente, devi avere una raccolta di "eventi" nel tuo database.
context.eventId
sarà sempre lo stesso su più invocazioni dello stesso trigger? Nei miei test sembra essere coerente, ma non riesco a trovare alcuna documentazione "ufficiale" che affermi questo.
Nel 2020 questo non è ancora disponibile in Firebase SDK, tuttavia è disponibile in Firebase Extensions (Beta), tuttavia è piuttosto complesso da configurare e utilizzare ...
Un approccio ragionevole
Helpers ... (creare / eliminare sembra ridondante ma è più economico di 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;
}
Ganci Firestore esportati
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 azione
Verrà tracciata la raccolta radice dell'edificio e tutte le raccolte secondarie .
Qui sotto il /counters/
percorso di root
Ora i conteggi delle raccolte verranno aggiornati automaticamente ed eventualmente! Se hai bisogno di un conteggio, usa semplicemente il percorso di raccolta e aggiungi il prefisso counters
.
const collectionPath = 'buildings/138faicnjasjoa89/buildingContacts';
const collectionCount = await db
.doc('counters/' + collectionPath)
.get()
.then(snap => snap.get('count'));
Sono d'accordo con @Matthew, costerà molto se esegui tale query.
[CONSIGLI PER GLI SVILUPPI PRIMA DI INIZIARE I LORO PROGETTI]
Dato che all'inizio abbiamo previsto questa situazione, possiamo effettivamente creare una raccolta, ovvero contatori con un documento, per archiviare tutti i contatori in un campo con tipo number
.
Per esempio:
Per ogni operazione CRUD sulla raccolta, aggiorna il documento contatore:
La prossima volta, quando si desidera ottenere il numero di raccolte, è sufficiente eseguire una query / puntare al campo del documento. [1 operazione di lettura]
Inoltre, è possibile memorizzare il nome delle raccolte in un array, ma questo sarà complicato, la condizione dell'array in firebase è mostrata di seguito:
// 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'}
Pertanto, se non si intende eliminare la raccolta, è possibile effettivamente utilizzare l'array per memorizzare l'elenco dei nomi delle raccolte anziché eseguire una query su tutta la raccolta ogni volta.
Spero che sia d'aiuto!
No, al momento non esiste un supporto integrato per le query di aggregazione. Tuttavia ci sono alcune cose che potresti fare.
Il primo è documentato qui . È possibile utilizzare le transazioni o le funzioni cloud per mantenere informazioni aggregate:
Questo esempio mostra come utilizzare una funzione per tenere traccia del numero di valutazioni in una raccolta secondaria, nonché della valutazione media.
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
});
});
});
});
La soluzione menzionata da jbb è utile anche se si desidera contare solo raramente i documenti. Assicurati di usare la select()
dichiarazione per evitare di scaricare tutti i documenti (è molta larghezza di banda quando hai solo bisogno di un conteggio). select()
è disponibile solo negli SDK del server per ora in modo tale soluzione non funzionerà in un'app mobile.
Non è disponibile alcuna opzione diretta. Non puoi farlo db.collection("CollectionName").count()
. Di seguito sono riportati i due modi in cui è possibile trovare il conteggio del numero di documenti all'interno di una raccolta.
db.collection("CollectionName").get().subscribe(doc=>{
console.log(doc.size)
})
Usando il codice sopra il tuo documento legge sarà uguale alla dimensione dei documenti all'interno di una raccolta e questo è il motivo per cui si deve evitare di usare la soluzione sopra.
db.collection("CollectionName").doc("counts")get().subscribe(doc=>{
console.log(doc.count)
})
Sopra abbiamo creato un documento con il conteggio dei nomi per memorizzare tutte le informazioni sul conteggio. Puoi aggiornare il documento conteggio nel modo seguente: -
wrt price (Document Read = 1) e veloce recupero dei dati la soluzione sopra è buona.
Incrementa un contatore usando 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 questo esempio incrementiamo un instanceCount
campo nel progetto ogni volta che un documento viene aggiunto alla instances
raccolta secondaria. Se il campo non esiste ancora, verrà creato e incrementato a 1.
L'incremento è transazionale internamente ma è necessario utilizzare un contatore distribuito se è necessario incrementare più frequentemente di ogni 1 secondo.
È spesso preferibile implementarlo onCreate
e onDelete
piuttosto che onWrite
richiedere gli onWrite
aggiornamenti, il che significa che stai spendendo più soldi per invocazioni di funzioni non necessarie (se aggiorni i documenti nella tua raccolta).
Una soluzione alternativa è:
scrivere un contatore in un documento firebase, che si incrementa all'interno di una transazione ogni volta che si crea una nuova voce
Memorizzi il conteggio in un campo della tua nuova voce (es .: posizione: 4).
Quindi si crea un indice su quel campo (posizione DESC).
Puoi eseguire un skip + limit con una query.Where ("position", "<" x) .OrderBy ("position", DESC)
Spero che questo ti aiuti!
Ho creato una funzione universale usando tutte queste idee per gestire tutte le contro-situazioni (tranne le query).
L'unica eccezione sarebbe quando fare così tante scritture al secondo, ti rallenta. Un esempio potrebbe essere il Mi piace su un post di tendenza. È eccessivo in un post sul blog, ad esempio, e ti costerà di più. Suggerisco di creare una funzione separata in quel caso usando i frammenti: 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);
});;
}
}
Gestisce eventi, incrementi e transazioni. Il bello di questo è che se non sei sicuro dell'accuratezza di un documento (probabilmente mentre sei ancora in beta), puoi eliminare il contatore per farlo aggiungere automaticamente al successivo trigger. Sì, questo costa, quindi non cancellarlo altrimenti.
Stesso tipo di cose per ottenere il conteggio:
const collectionPath = 'buildings/138faicnjasjoa89/buildingContacts';
const colSnap = await db.doc('_counters/' + collectionPath).get();
const count = colSnap.get('count');
Inoltre, potresti voler creare un processo cron (funzione pianificata) per rimuovere i vecchi eventi per risparmiare denaro sull'archiviazione del database. È necessario almeno un piano di incendio e potrebbe esserci qualche altra configurazione. Potresti eseguirlo ogni domenica alle 23:00, per esempio. https://firebase.google.com/docs/functions/schedule-functions
Questo non è testato , ma dovrebbe funzionare con alcune modifiche:
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;
});
E infine, non dimenticare di proteggere le raccolte in firestore.rules :
match /_counters/{document} {
allow read;
allow write: if false;
}
match /_events/{document} {
allow read, write: if false;
}
Aggiornamento: query
Aggiungendo all'altra mia risposta se si desidera automatizzare anche il conteggio delle query, è possibile utilizzare questo codice modificato nella funzione cloud:
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();
Che aggiornerà automaticamente postsCount in userDocument. In questo modo puoi facilmente aggiungere un altro a molti conteggi. Questo ti dà solo idee su come puoi automatizzare le cose. Ti ho anche dato un altro modo per eliminare gli eventi. Devi leggere ogni data per eliminarla, quindi non ti salverà davvero per eliminarli in un secondo momento, rende la funzione più lenta.
/**
* 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;
}
Dovrei anche avvertirti che le funzioni universali verranno eseguite su ogni periodo di chiamata onWrite. Potrebbe essere più economico eseguire la funzione solo su istanze onCreate e onDelete delle raccolte specifiche. Come il database noSQL che stiamo utilizzando, codice e dati ripetuti possono farti risparmiare denaro.
Mi ci è voluto un po 'per farlo funzionare in base ad alcune delle risposte sopra, quindi ho pensato di condividerlo per gli altri. Spero sia utile
'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;
});
Ho provato molto con approcci diversi. E infine, perfeziono uno dei metodi. Per prima cosa devi creare una raccolta separata e salvare lì tutti gli eventi. In secondo luogo è necessario creare un nuovo lambda per essere attivato dal tempo. Questa lambda conterà gli eventi nella raccolta degli eventi e cancellerà i documenti degli eventi. Dettagli del codice nell'articolo. https://medium.com/@ihor.malaniuk/how-to-count-documents-in-google-cloud-firestore-b0e65863aeca
Questa query comporterà il conteggio del documento.
this.db.collection(doc).get().subscribe((data) => {
count = data.docs.length;
});
console.log(count)
Questo utilizza il conteggio per creare un ID numerico univoco. Nel mio uso, non diminuirò mai , anche quando document
l'ID è necessario per l'eliminazione.
Su una collection
creazione che richiede un valore numerico univoco
appData
con un documento, set
con .doc
IDonly
uniqueNumericIDAmount
su 0 infirebase firestore console
doc.data().uniqueNumericIDAmount + 1
come ID numerico univocoappData
raccolta uniqueNumericIDAmount
confirebase.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();
}
});