Я думаю о двух возможных подходах.
1.Непосредственно посчитайте документ коллекции
Вы бы использовали size
свойство QuerySnapshot
как
admin.firestore().collection('groups/{groupId}/members/{memberId}')
.get()
.then(querySnapshot => {
console.log(querySnapshot.size);
//....
return null;
});
Основная проблема здесь - это стоимость , если подколлекция содержит много документов: при выполнении этого запроса с вас будет взиматься плата за одно чтение для каждого документа подпункта.коллекция.
2.Другой подход состоит в том, чтобы поддерживать некоторые счетчики для каждой подгруппы
. Вы бы написали две облачные функции на основе распределенных счетчиков , как представлено в этой базе данных Firebase.элемент документации: https://firebase.google.com/docs/firestore/solutions/counters. В следующем примере мы используем 3 осколка.
Во-первых, облачная функция увеличивает счетчик при добавлении нового документа в подгруппу subCollec
:
//....
const num_shards = 3;
//....
exports.incrementSubCollecCounter = functions
.firestore.document('groups/{groupId}/members/{memberId}')
.onCreate((snap, context) => {
const groupId = context.params.groupId;
const shard_id = Math.floor(Math.random() * num_shards).toString();
const shard_ref = admin
.firestore()
.collection('shards' + groupId)
.doc(shard_id);
if (!snap.data().counterIncremented) {
return admin.firestore().runTransaction(t => {
return t
.get(shard_ref)
.then(doc => {
if (!doc.exists) {
throw new Error(
'Shard doc #' +
shard_id +
' does not exist.'
);
} else {
const new_count = doc.data().count + 1;
return t.update(shard_ref, { count: new_count });
}
})
.then(() => {
return t.update(snap.ref, {
counterIncremented: true //This is important to have the Function idempotent, see https://cloud.google.com/functions/docs/bestpractices/tips#write_idempotent_functions
});
});
});
} else {
console.log('counterIncremented NOT NULL');
return null;
}
});
Тогда вторая облачная функция уменьшит счетчик при удалении документа из подгруппы subCollec
:
exports.decrementSubCollecCounter = functions
.firestore.document('groups/{groupId}/members/{memberId}')
.onDelete((snap, context) => {
const groupId = context.params.groupId;
const shard_id = Math.floor(Math.random() * num_shards).toString();
const shard_ref = admin
.firestore()
.collection('shards' + groupId)
.doc(shard_id);
return admin.firestore().runTransaction(t => {
return t.get(shard_ref).then(doc => {
if (!doc.exists) {
throw new Error(
'Shard doc #' +
shard_id +
' does not exist.'
);
} else {
const new_count = doc.data().count - 1;
return t.update(shard_ref, { count: new_count });
}
});
});
});
Здесь, сравните с решением 1, так как у нас есть 3 осколкаЕсли вы хотите узнать количество документов в подгруппе subCollec
, вам нужно прочитать только 3 документа.
Посмотрите в документации подробности инициализации распределенных счетчиков.Вы должны инициализировать один раз для каждой коллекции groupId (т.е. admin.firestore().collection('shards' + groupId)
)