Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
351 views
in Technique[技术] by (71.8m points)

Angular + Firebase firestore - inner subscription to document returns two values on initial subscribe

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.

  1. What am I doing wrong in sample code potentially?

  2. Does anyone have advice on how should I retrieve data more efficiently with less reads?

  3. 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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Here is what I would do in your situation:

  1. Do a onSnapshot() query, (the first read operation) --> But limit results to 10 or 20. (cheap!)
  2. On user scroll -> load more. (Firestore pagination ref)
  3. When a document change --> update the displayed data

When listening for changes, you're only charged again for the documents that did change, not the ones you already queried that didn't get any updates.

For more details on pricing for listeners, watch this video (especially at 3:16)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...