2

I am trying to combine multiple streams that comes from Cloud Firestore as a result of WHERE IN Query. One drawback of this query is that it is limited to only 10 values in one query. But I have list which has more than 10 values so I query every 10 values from that list in one WHERE IN query and get result as Stream<List<Product>>. So in the end I want to combine all streams from all query into one Stream<List<Product>> and return that Stream<List<Product>> from my function.

This is the code that I am using:

Stream<List<Product>> cartProductsStream(List<List<int>> idGroupList) {

// idGroupList = [[1,2,3,4,5,6,7,8,9,10], [11,12,13,14,15]];

// here I am querying from firestore for every list from idGroupList.
for (List<int> listOfTen in idGroupList) {
    Stream<List<Product>> resultList = _db
        .collection('products')
        .where('id', whereIn: listOfTen)
        .snapshots()
        .map((event) => event.documents
            .map((e) => Product.fromJson(
                  e.data,
                ))
            .toList());
  }
}

From here I want to combine every resultList stream into one stream and return that stream. How can I achieve that? Thanks in advance.

UPDATE

For whom it might interest. With guidance of @pskink and @EdwardLi i solved my problem like this:

my function for streams:

List<Stream<List<Product>>> cartProductsStream(List<List<int>> idGroupList) {

  // idGroupList = [[1,2,3,4,5,6,7,8,9,10], [11,12,13,14,15]];

  List<Stream<List<Product>>> streamList = [];

  for (List<int> listOfTen in idGroupList) {
      Stream<List<Product>> resultList = _db
          .collection('products')
          .where('id', whereIn: listOfTen)
          .snapshots()
          .map((event) => event.documents
              .map((e) => Product.fromJson(
                    e.data,
                  ))
              .toList());

      streamList.add(resultList);
    }

    return streamList;
}

my StreamBuilder widget:

StreamBuilder(
            stream: CombineLatestStream.list(stream.cartProductsStream(
                idList.toList())), // to combine streamList into one. return type List<List<Product>>
            builder: (ctx, snapshot) { 
              if (snapshot.connectionState == ConnectionState.waiting) {
                return Center(
                  child: LoadingPage(),
                );
              }
              // here snapshot data is List<List<Product>> type. so in this for loop i add all List<Product> into one 
              for (List<Product> fbList in snapshot.data) {
                fbProducts.addAll(fbList.toSet());
              }});
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
RuslanBek
  • 1,592
  • 1
  • 14
  • 30
  • `StreamZip` maybe? or `CombineLatestStream` from `rxdart`? it all depends on how you want to combine them – pskink Feb 19 '21 at 20:12
  • 1
    here is a solution using `CombineLatestStream`, I hope it will help you https://stackoverflow.com/a/61597077/13914375 – EdwardLi Feb 19 '21 at 20:19
  • @pskink i am new in this framework. could you show me your solution in my case example? – RuslanBek Feb 20 '21 at 08:32
  • this is how you can use `CombineLatestStream`: https://stackoverflow.com/a/54699726/2252830 – pskink Feb 20 '21 at 08:35
  • thank you @pskink for quick reply. i have last quick question. i now get that `CombineLatestStream` do combine all streams. now how can i combine to make list of `resultList` streams in above `for in loop`? i tried this `List>> streamList;` and add `resultList` into `streamList` but gives error `add called on null` why? – RuslanBek Feb 20 '21 at 09:03
  • `streamList` is `null` - it has to be initialized first – pskink Feb 20 '21 at 09:26
  • @pskink please help me on this. – RuslanBek Feb 20 '21 at 09:53
  • no, `List>> streamList;` is not initialized, see https://dart.dev/guides/language/language-tour#default-value - first read some tutorials on collections like https://dart.dev/codelabs/iterables#:~:text=An%20Iterable%20is%20a%20collection,a%20new%20List%20or%20Set%20. – pskink Feb 20 '21 at 10:09
  • @pskink yeah i got it. i was not initializing above. thank you for your help! – RuslanBek Feb 20 '21 at 10:17

1 Answers1

0

You can use a empty list and add the elements

Stream<List<Product>> cartProductsStream(List<List<int>> idGroupList) {

  List<Product> returnProducts = [];

  // idGroupList = [[1,2,3,4,5,6,7,8,9,10], [11,12,13,14,15]];

  // here I am querying from firestore for every list from idGroupList.
  for (List<int> listOfTen in idGroupList) {
    Stream<List<Product>> resultList = _db
        .collection('products')
        .where('id', whereIn: listOfTen)
        .snapshots()
        .map((event) => event.documents
            .map(
              (e) => returnProducts.add(
                Product.fromJson(e.data)
              )
            ));
  }
}
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459