Bir koleksiyonun yeni Firebase veritabanı Cloud Firestore'u kullanarak kaç öğeye sahip olduğunu saymak mümkün mü?
Öyleyse, bunu nasıl yaparım?
Bir koleksiyonun yeni Firebase veritabanı Cloud Firestore'u kullanarak kaç öğeye sahip olduğunu saymak mümkün mü?
Öyleyse, bunu nasıl yaparım?
Yanıtlar:
Birçok soruda olduğu gibi, cevap - O bağlıdır .
Ön uçta büyük miktarda veri tutarken çok dikkatli olmalısınız. Ön uçunuzu ağır hissettirmenin yanı sıra , Firestore ayrıca yaptığınız milyon okuma başına 0,60 dolar alıyor .
Dikkatli kullanın - Kullanıcı arabirimi kullanıcısı deneyimi isabet alabilir
Bu döndürülen dizi ile çok fazla mantık yapmadığınız sürece bunu ön uçta işlemek iyi olmalıdır.
db.collection('...').get().then(snap => {
size = snap.size // will return the collection size
});
Dikkatli kullanın - Firestore okuma çağrıları çok pahalıya mal olabilir
Bunu kullanıcı tarafında yavaşlatmak için çok fazla potansiyele sahip olduğundan ön uçta işlem yapmak uygun değildir. Bu mantık sunucusu tarafını işlemeli ve yalnızca boyutu döndürmeliyiz.
Bu yöntemin dezavantajı, hala uzun süre beklediğinizden daha pahalıya mal olabilecek firestore okumalarını (koleksiyonunuzun boyutuna eşit) çağırmanızdır.
Bulut İşlevi:
...
db.collection('...').get().then(snap => {
res.status(200).send({length: snap.size});
});
Başlangıç aşaması:
yourHttpClient.post(yourCloudFunctionUrl).toPromise().then(snap => {
size = snap.length // will return the collection size
})
En ölçeklenebilir çözüm
FieldValue.increment ()
Nisan 2019 itibariyle Firestore, sayaçları tamamen atomik olarak ve daha önce verileri okumadan artırmaya izin veriyor . Bu, aynı anda birden fazla kaynaktan güncelleme yaparken (daha önce işlemler kullanılarak çözülmüşken) doğru sayaç değerlerine sahip olmamızı sağlarken, gerçekleştirdiğimiz veritabanı okumalarının sayısını da azaltır.
Herhangi bir belgeyi dinleyerek siler veya oluşturur, veritabanında oturan bir sayım alanına ekleyebilir veya kaldırabilirsiniz.
Firestore belgelerine bakın - Dağıtılmış Sayıcılar Veya Jeff Delaney tarafından Veri Toplamaya bir göz atın . Rehberleri AngularFire kullanan herkes için gerçekten harika ama dersleri başka çerçevelere de taşınmalı.
Bulut İşlevi:
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;
});
Şimdi ön uçta koleksiyonun boyutunu almak için bu numberOfDocs alanını sorgulayabilirsiniz.
firestore.runTransaction { ... }
blok halinde tamamlamaları gerektiğini eklemek isterim . Bu, erişimle ilgili eşzamanlılık sorunlarını giderir numberOfDocs
.
Bunu yapmanın en basit yolu bir "querySnapshot" boyutunu okumaktır.
db.collection("cities").get().then(function(querySnapshot) {
console.log(querySnapshot.size);
});
"QuerySnapshot" içindeki docs dizisinin uzunluğunu da okuyabilirsiniz.
querySnapshot.docs.length;
Veya bir boolean değeri döndürecek boş değeri okuyarak bir "querySnapshot" boşsa.
querySnapshot.empty;
db.collection.count()
. Onları sadece bunun için bırakmayı düşünüyorum
Bildiğim kadarıyla bunun için yerleşik bir çözüm yoktur ve sadece şu anda sdk düğümünde mümkündür. Eğer bir
db.collection('someCollection')
kullanabilirsiniz
.select([fields])
hangi alanı seçmek istediğinizi tanımlamak için. Boş bir select () yaparsanız, bir dizi belge başvurusu alırsınız.
misal:
db.collection('someCollection').select().get().then(
(snapshot) => console.log(snapshot.docs.length)
);
Bu çözüm yalnızca tüm belgeleri indirmenin en kötü durumu için bir optimizasyondur ve büyük koleksiyonlarda ölçeklenmez!
Ayrıca şuna da göz atın:
Cloud Firestore ile bir koleksiyondaki sayıdaki belge sayısını alma
select(['_id'])
daha hızlıselect()
Büyük koleksiyonlar için doküman sayısını saymaya dikkat edin . Her koleksiyon için önceden hesaplanmış bir sayaç istiyorsanız, firestore veritabanı ile biraz karmaşıktır.
Böyle bir kod bu durumda çalışmaz:
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;
});
Bunun nedeni, yangın deposu belgelerinin dediği gibi her bulut firestore tetikleyicisinin idempotent olması gerektiğidir: https://firebase.google.com/docs/functions/firestore-events#limitations_and_guarantees
Bu nedenle, kodunuzun birden çok yürütülmesini önlemek için olaylar ve işlemlerle yönetmeniz gerekir. Bu benim büyük toplama sayaçları işlemek için benim özel yoludur:
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;
});
Buradaki vakaları kullanın:
/**
* 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'));
Gördüğünüz gibi, birden fazla yürütmeyi önlemenin anahtarı , bağlam nesnesindeki eventId adı verilen özelliktir . İşlev aynı olay için birçok kez işlenmişse, olay kimliği her durumda aynı olacaktır. Maalesef, veritabanınızda "etkinlikler" koleksiyonunuzun olması gerekir.
context.eventId
Aynı tetikleyicinin birden çok çağrısında bunun her zaman aynı olacağını doğrulayabilir miyiz ? Testlerimde tutarlı görünüyor, ancak bunu belirten herhangi bir "resmi" belge bulamıyorum.
2020'de bu Firebase SDK'sında hala mevcut değildir, ancak Firebase Uzantıları'nda (Beta) mevcuttur, ancak kurulumu ve kullanımı oldukça karmaşıktır ...
Makul bir yaklaşım
Yardımcıları ... (oluşturma / silme gereksiz görünüyor ancak onUpdate'den daha ucuz)
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;
}
İhraç edilen Firestore kancaları
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());
});
Eylemde
Yapı kökü koleksiyonu ve tüm alt koleksiyonlar izlenecektir.
Burada /counters/
kök yolunun altında
Şimdi toplama sayıları otomatik ve sonunda güncellenecek! Bir sayıya ihtiyacınız varsa, toplama yolunu kullanın ve önekini ekleyin counters
.
const collectionPath = 'buildings/138faicnjasjoa89/buildingContacts';
const collectionCount = await db
.doc('counters/' + collectionPath)
.get()
.then(snap => snap.get('count'));
@Matthew ile hemfikirim, böyle bir sorgu yaparsanız çok maliyetli olacaktır .
[PROJELERİNE BAŞLAMADAN ÖNCE GELİŞTİRİCİLER İÇİN TAVSİYE]
Başlangıçta bu durumu öngördüğümüz için, aslında tüm sayaçları tür içeren bir alanda saklamak için bir belgeyle bir sayaç gibi bir koleksiyon yapabiliriz number
.
Örneğin:
Koleksiyondaki her CRUD işlemi için sayaç belgesini güncelleyin:
Bir dahaki sefere, koleksiyon sayısını almak istediğinizde, belge alanını sorgulamanız / işaret etmeniz yeterlidir. [1 okuma işlemi]
Ayrıca, koleksiyon adını bir dizide saklayabilirsiniz, ancak bu zor olacaktır, firebase'deki dizinin durumu aşağıdaki gibi gösterilir:
// 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'}
Bu nedenle, koleksiyonu silmeyecekseniz, her seferinde tüm koleksiyonu sorgulamak yerine koleksiyon adı listesini saklamak için dizi kullanabilirsiniz.
Umarım yardımcı olur!
Hayır, şu anda toplama sorguları için yerleşik bir destek yok. Ancak yapabileceğiniz birkaç şey var.
İlki burada belgelenmiştir . Toplu bilgileri korumak için işlemleri veya bulut işlevlerini kullanabilirsiniz:
Bu örnek, bir alt toplamadaki derecelendirme sayısını ve ortalama derecelendirmeyi izlemek için bir işlevin nasıl kullanılacağını gösterir.
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
});
});
});
});
Jbb'nun bahsettiği çözüm, belgeleri nadiren saymak istiyorsanız da yararlıdır. select()
Her belgeyi indirmekten kaçınmak için ifadeyi kullandığınızdan emin olun (bu yalnızca bir sayıya ihtiyacınız olduğunda çok fazla bant genişliğidir). select()
şimdilik sunucu SDK'larında kullanılabilir, böylece çözüm bir mobil uygulamada çalışmaz.
Doğrudan seçenek yoktur. Yapamazsın db.collection("CollectionName").count()
. Bir koleksiyondaki belge sayısını bulabilmenin iki yolu aşağıdadır.
db.collection("CollectionName").get().subscribe(doc=>{
console.log(doc.size)
})
Yukarıdaki kodu kullanarak, belge okumalarınız bir koleksiyondaki belgelerin boyutuna eşit olacaktır ve bu yüzden yukarıdaki çözümü kullanmaktan kaçınmanız gerekir.
db.collection("CollectionName").doc("counts")get().subscribe(doc=>{
console.log(doc.count)
})
Yukarıda, tüm sayım bilgilerini saklamak için ad sayımlarına sahip bir belge oluşturduk. Sayım belgesini aşağıdaki şekilde güncelleyebilirsiniz: -
wrt fiyat (Belge Okuma = 1) ve yukarıdaki çözüm hızlı veri alma iyidir.
Admin.firestore.FieldValue.increment komutunu kullanarak bir sayacı artırın :
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),
})
);
Bu örnekte instanceCount
, instances
alt koleksiyona her belge eklendiğinde projedeki bir alanı artırıyoruz . Alan henüz mevcut değilse, oluşturulacak ve 1'e artırılacaktır.
Artım dahili olarak işlemseldir, ancak her 1 saniyeden daha sık artırmanız gerekiyorsa dağıtılmış bir sayaç kullanmalısınız .
Uygulamayı uygulamak genellikle tercih edilir onCreate
ve güncellemeleri çağırmak onDelete
yerine gereksiz işlev çağrıları için daha fazla para harcadığınız anlamına gelir (koleksiyonunuzdaki dokümanları güncellerseniz).onWrite
onWrite
Çözüm:
her yeni giriş oluşturduğunuzda bir işlemde artırdığınız bir ateş tabanı belgesine sayaç yazma
Sayımı yeni girişinizin bir alanında saklarsınız (örneğin: konum: 4).
Sonra bu alanda bir dizin oluşturun (DESC konumu).
Bir sorgu ile bir atlama + sınırı yapabilirsiniz. ("Position", "<" x) .OrderBy ("position", DESC)
Bu yardımcı olur umarım!
Tüm sayaç durumlarını (sorgular hariç) ele almak için tüm bu fikirleri kullanarak evrensel bir işlev oluşturdum.
Tek istisna, bu kadar çok yazar bir saniye yazarken sizi yavaşlatır. Bir örnek, popüler bir gönderideki beğeniler olabilir . Örneğin, bir blog yazısında aşırıya kaçıyor ve size daha pahalıya mal olacak. Bu durumda kırıkları kullanarak ayrı bir işlev oluşturmanızı öneririm: 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);
});;
}
}
Bu olayları, artışları ve işlemleri yönetir. Bunun güzelliği, bir belgenin doğruluğundan emin değilseniz (muhtemelen hala betadayken), bir sonraki tetikleyiciye otomatik olarak eklemesi için sayacı silebilirsiniz. Evet, bu maliyet, bu yüzden başka şekilde silmeyin.
Sayımı almak için aynı tür şeyler:
const collectionPath = 'buildings/138faicnjasjoa89/buildingContacts';
const colSnap = await db.doc('_counters/' + collectionPath).get();
const count = colSnap.get('count');
Ayrıca, veritabanı depolama alanından tasarruf etmek için eski olayları kaldırmak üzere bir cron işi (zamanlanmış işlev) oluşturmak isteyebilirsiniz. En azından bir yangın planına ihtiyacınız var ve biraz daha yapılandırma olabilir. Mesela her pazar saat 11'de çalıştırabilirsiniz. https://firebase.google.com/docs/functions/schedule-functions
Bu test edilmemiştir , ancak birkaç değişiklikle çalışmalıdır:
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;
});
Ve de koleksiyonlarını korumak için son unutma firestore.rules :
match /_counters/{document} {
allow read;
allow write: if false;
}
match /_events/{document} {
allow read, write: if false;
}
Güncelleme: Sorgular
Sorgu sayılarını da otomatikleştirmek istiyorsanız diğer yanıtıma ekleyerek, bulut işlevinizde bu değiştirilmiş kodu kullanabilirsiniz:
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();
Hangi userDocument içindeki postsCount değerini otomatik olarak güncelleyecektir . Bu şekilde birçok sayıya kolayca başka bir sayı ekleyebilirsiniz. Bu size bir şeyi nasıl otomatik hale getirebileceğiniz konusunda fikir verir. Ayrıca size etkinlikleri silmenin başka bir yolunu verdim. Silmek için her tarihi okumak zorundasınız, böylece daha sonra silmek için sizi gerçekten kurtarmaz, sadece işlevi yavaşlatır.
/**
* 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;
}
Ayrıca, evrensel işlevlerin her onWrite çağrı döneminde de çalışacağı konusunda sizi uyarmalıyım. İşlevi yalnızca özel koleksiyonlarınızın onCreate ve onDelete örneklerinde çalıştırmak daha ucuz olabilir. Kullandığımız noSQL veritabanı gibi, tekrarlanan kod ve veriler paradan tasarruf etmenizi sağlayabilir.
Yukarıdaki cevaplardan bazılarına dayanarak bu çalışmayı elde etmek için biraz zamanımı aldım, bu yüzden başkalarının kullanması için paylaşacağımı düşündüm. Umarım faydalıdır.
'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;
});
Farklı yaklaşımlarla çok şey denedim. Ve son olarak, yöntemlerden birini geliştiriyorum. Öncelikle ayrı bir koleksiyon oluşturmanız ve orada tüm etkinlikleri kaydetmeniz gerekir. İkincisi, zamanla tetiklenecek yeni bir lambda oluşturmanız gerekiyor. Bu lambda olay toplama ve açık olay belgelerindeki olayları sayar. Makalede kod ayrıntıları. https://medium.com/@ihor.malaniuk/how-to-count-documents-in-google-cloud-firestore-b0e65863aeca
Bu sorgu belge sayısıyla sonuçlanacaktır.
this.db.collection(doc).get().subscribe((data) => {
count = data.docs.length;
});
console.log(count)
Bu, sayısal benzersiz kimlik oluşturmak için saymayı kullanır. Kullanımım sırasında , kimliğin gerekli olduğu silinmiş olsa bile, hiç azalmayacağımdocument
.
collection
Benzersiz sayısal değer gerektiren bir oluşturma üzerine
appData
, tek belgeyle set
birlikte .doc
idonly
uniqueNumericIDAmount
0 olarak ayarlayınfirebase firestore console
doc.data().uniqueNumericIDAmount + 1
Benzersiz sayısal kimlik olarak kullanappData
Koleksiyonu şu uniqueNumericIDAmount
şekilde güncelleyin: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();
}
});