I'm using AngularFire as my API for firebase on Angular 11+.
The domain of my app are real-time auctions
What I'd like to do ideally is read all documents and then subscribe to each one for changes.
My troubles currently are the number of reads I'm making on firestore.
My collection read will yield N reads. But subscribing to each document will yield additional read making it by default 2N reads which seems to be inevitable.
But I guess it's better than to leave a subscription on the collection and receiving N reads each time something from the collection is updated.
So with the sample code below, I make a query to collection and then another query to the document. Simplified just for repro.
this.store.collection("users").valueChanges()
.pipe(
take(1),
concatMap(() => this.store.doc("user/1").valueChanges())
)
.subscribe(console.log(user));
However, Inner observable will emit 2 times.
Once with added
and one with modified
snapshot change type.
So my question is:
Why does my inner observable emit two times in a row on initial subscribe when it seems to me like it should emit only once.
If both of those emits count as reads on firestore this would yield 3N reads.
By my testing on firestore monitoring page, it seems to be the case since on the 400 document page I had about 1200 reads recorded on firestore and counted in pricing.
What am I doing wrong in sample code potentially?
Does anyone have advice on how should I retrieve data more
efficiently with less reads?
Should I switch to RTDB which seems to have more generous offer of
10GB data output which could be better for my reads volume?
Edit:
So I just tested with angularfire API for firebase RTDB.
Sample code like above would make inner observable emit just 1 value as expected and 1 per item change. Which is expected.
Still not clear to me exactly why firestore implementation would emit 2 values which both count as read and take away on pricing.
End code would look something like this:
this.db.list<AuctionItem>(`auctions/1/items`)
.valueChanges()
.pipe(
take(1),
tap(items => this.itemsToRender = items),
mergeMap(items => [...items]),
mergeMap((item: AuctionItem) => this.db.object(`auctions/1/items/${item.id}`).valueChanges() as Observable<AuctionItem>),
)
.subscribe(change => {
// do work when item updates
})
Still not sure why firestore isn't working for me as expected. Thinking about having partial firestore + RTDB for optimal usage since reads are going high for me on firestore even with 50k free.
question from:
https://stackoverflow.com/questions/65926897/angular-firebase-firestore-inner-subscription-to-document-returns-two-values