0

This is a follow-up question to the question asked here. Long story short, I'm trying to limit a Flutter Firebase query only to values contained in a list.

Here's the working code with an additional question at the end. Using the 'shares' collection and adding an ID field to the 'projects' collection as below:

Shares db

Projects db

I'm now able to use one Stream to retrieve my shares (per user), and then use that list as a query in a second Stream like so:

@override
Stream<Map<String, dynamic>> getUserSharesStream({@required String uid}) {
  return _firestore.collection('shares').doc(uid).snapshots().map((doc) => doc.data());
}

@override
Stream<List<Map>> getListOfProjectsForUser({@required String uid, @required List<String> shares}) {
  var ref = _firestore.collection('projects');
  return ref
      .where('id', whereIn: shares)
      .snapshots()
      .map((QuerySnapshot snapshot) => snapshot.docs.map((DocumentSnapshot doc) => doc.data()).toList());
}

In the app, I get a list of the projects shared with my user like so:

stream: userSharesQuery,
builder: (BuildContext context, AsyncSnapshot snapshot) {
  if (snapshot.hasData) {
    Map<String, dynamic> result = snapshot.data;
    projectsList = result.keys.toList();

By feeding that list into my projectsListStream.builder I get a list of the projects shared with my user, which was the answer to the original question.

My remaining question is: apparently I'm limited to 10 items in my query limit list. So how would YOU architect for instances where the number of shared projects is GREATER than 10?

Should I just abandon trying to limit my queries and simply parse the entire list of projects every time, looking for projectIds that match my user's share list? Or is there a way to call the stream more than once, each time with a list of 10? Or would you recommend an entirely different scheme for accomplishing the task?

user4157124
  • 2,809
  • 13
  • 27
  • 42
ConleeC
  • 337
  • 6
  • 13

1 Answers1

1

I know I'm a bit late but I was trying to come up with something similar so this can help if someone wants to use snapshot instead of get to have a realtime stream

using rx package CombineLatestStream.list you can have multiple streams splitted with an array of lenght 10 or less and then combine them

@override
Stream<List<Map>> getListOfProjectsForUser({@required String uid, @required List<String> shares}) {
  var ref = _firestore.collection('projects');
  return CombineLatestStream.list<QuerySnapshot>([
   for(int i = 0; i < shares.length; i += 10)  //steps of 10, the maximum an array in WhereIn can handle
      ref.where(FieldPath.documentId,
         whereIn: shares.getRange(i,
           i+10 > shares.length ? i + (shares.length % 10) : i+10).toList() // at the end if the array is not a multiple of 10 return the remainder
         ).snapshots()
  ]).map((event) => 
    event.expand((qDocument) => qDocument.docs.map((DocumentSnapshot doc) => doc.data())).toList()
  );
}
EdwynZN
  • 4,895
  • 2
  • 12
  • 15