Как я могу иметь дело с firestore, где в пределах 10 при использовании потока переключения?

У меня есть следующий поток, который принимает поток группы и возвращает поток ее членов. Я использую карту переключателей, чтобы получить участников из снимка группы.

Но у меня такая проблема. Я использую запрос where с фильтром whereIn. Но проблема в том, что whereIn может принимать только список, который имеет 10 или меньше записей в соответствии с документацией firestore.

Ограничения Обратите внимание на следующие ограничения для in и array-contains-any:

in и array-contains-any поддерживают до 10 сравнительных значений.

https://firebase.google.com/docs/firestore/query-data/queries#limitations

Так что у меня есть некоторые трудности с этим в этом сенарио.

  Stream<List<UserModel>> groupMembersStream(Stream<GroupModel> groupStream) {
    return groupStream.switchMap(
      (value) => _fireStore
          .collection(APIRoutes.users)
          .where(FieldPath.documentId, whereIn: value.members.keys.toList(growable: false))
          .snapshots()
          .map((snapshot) =>
              snapshot.documents.map((document) => UserModel.fromFirestore(document)).toList(growable: false)),
    );
  }

Потому что мне нужен идентификатор члена группы для начала, поэтому мне нужен switchMap. Поэтому я не могу просто разделить список участников группы, а затем выполнить отдельный запрос для каждого фрагмента из 10 идентификаторов.

Итак, как мне с этим справиться?


person Mike Ottink    schedule 19.05.2020    source источник


Ответы (2)


Другое возможное решение (с использованием Quiver & RxDart пакетов)

  Future<List<QueryDocumentSnapshot>> listItems(
      List<dynamic> itemIds) async {
    final chunks = partition(itemIds, 10);
    final querySnapshots = await Future.wait(chunks.map((chunk) {
      Query itemsQuery = FirebaseFirestore.instance
          .collection('collection')
          .where("id", whereIn: chunk);
      return itemsQuery.get();
    }).toList());
    return querySnapshots == null
        ? []
        : await Stream.fromIterable(querySnapshots)
            .flatMap((qs) => Stream.fromIterable(qs.docs))
            .toList();
  }

Этот способ выглядит более общим (вы даже можете выделить запрос с помощью функции поставщика).

person xfyre    schedule 12.11.2020

В итоге я сделал это вот так

  Stream<List<UserModel>> groupMembersStream(Stream<GroupModel> groupStream) {
    return groupStream.switchMap(
      (value) => _chunckSizeGroupMembersStream(value),
    );
  }

  Stream<List<UserModel>> _chunckSizeGroupMembersStream(GroupModel group) {
    final List<List<String>> memberChunks = chunkSizeCollection(group.members.keys.toList(growable: false), 10);
    List<Stream<List<UserModel>>> streams = List<Stream<List<UserModel>>>();
    memberChunks.forEach((chunck) => streams.add(_fireStore
        .collection(APIRoutes.userCollection)
        .where(FieldPath.documentId, whereIn: chunck)
        .snapshots()
        .map((snapshot) =>
            snapshot.documents.map((document) => UserModel.fromFirestore(document)).toList(growable: false))));
    return ZipStream(streams, (value) => value.last);
  }
person Mike Ottink    schedule 24.05.2020
comment
что такое chunkSizeCollection? - person Alex Efimov; 17.01.2021
comment
Firestore whereIn имеет ограничение в 10 элементов. ChunkSizeCollection просто разбивает массив на куски по 10 элементов. - person Mike Ottink; 17.01.2021
comment
Майк, я адаптировал этот код и получаю отказ. Метод add был вызван с нулевым значением. Получатель: null Попытка вызвать: добавить (Экземпляр '_MapStream ‹QuerySnapshot, List ‹AttendeeData››'). .Add требует ожидания ... вы не понимаете? Проблема, с которой я сталкиваюсь, заключается в том, что для ожидания требуется будущее, которое сокращает поток. интересно, может я что-то упускаю. - person jbryanh; 14.02.2021