1
votes

I have a collection in Firebase's Cloud Firestore database with subcollections like so:

myCollection
    doc1
        statistics
            doc1
            doc2
            doc3
    doc2
        statistics
            doc1
            doc2
    doc3
        statistics
            doc1
            doc2
            doc3
            doc4
    doc4
        statistics

and so on.

Based off of a query, I pull maybe doc1, doc2, and doc4 from the collection, for example. Now, for each of those, I need to query their respective subcollections for relevant statistics.

My solution in my AngularJS app so far has been:

/**
 * Gets aggregate views for queried docs.
 * @param {![firebase.firestore.DocumentSnapshot]} docs - the queried documents 
 */
$scope.getTotalViews = (docs) => {
    let promises = [];
    docs.forEach(doc => {
        promises.push($scope.getTotalDocumentViews(doc.id));
    });
    $q.all(promises).then(totalViewsArray => {
        // TODO: Sum the array to get aggregate views for queried documents
        // Only outputs some of the time
        console.log(totalViewsArray);
    });
};

/**
 * Gets all view statistics from a given document's subcollection.
 */
$scope.getTotalDocumentViews = (id) => {
    let deferred = $q.defer();
    firebase.firestore().collection("myCollection").doc(id).collection("statistics").where("type", "==", "view").get().then(snapshot => {
        deferred.resolve(snapshot.size);
    });
    return deferred.promise;
};

The problem I am running into is since there can be many documents that are returned by the query on myCollection, looping through all of these and querying their subcollections seems grossly inefficient. Not only that but, while the above code does succeed some of the time, a lot of the time it throws the error:

Uncaught (in promise) Error: transaction closed

I have also tried to perform the multiple subcollection queries in a transaction, but this has not worked as well since I am not retrieving just one doc, but rather querying for potentially hundreds from the subcollection.

How do I efficiently query the subcollections of some set of multiple documents?

1

1 Answers

1
votes

I think the same applies here as to most other NoSQL databases (and definitely the Firebase Realtime Database): if you want to be able to efficiently get the count of something from the database, you should store that count as a property and update it continuously (in this case) views occur. Trying to read hundreds of documents just to determine their count isn't going to scale.

So consider adding a view_count property to each document, and increment that (likely with a transaction) as you record views.