Есть ли способ группировки и сопоставления нескольких потоков коллекций? - PullRequest
0 голосов
/ 23 марта 2020

У меня есть пользовательская коллекция в firestore, которая имеет 2 подколлекции, private и publi c. Я хочу получить пользовательскую модель в потоке. Поэтому я получаю снимок пользовательского документа и сопоставляю его с моделью пользователя. Но как это работает, когда у меня есть эти две подколлекции? Потому что обе подколлекции будут нуждаться в собственном потоке, верно? Как я могу объединить это в одну модель пользователя? Это то, что у меня до сих пор, моя проблема началась, когда я пытался получить частные и опубликованные подколлекции c в моей пользовательской модели из моего снимка и понял, что они оба являются их собственным потоком. Кроме того, я бы хотел, чтобы любые асин c вещи не попадали в мою модель пользователя. Теперь я думаю, что мне нужно каким-то образом создать поток, который отображает оба документа вспомогательной коллекции на одну модель, но как мне это сделать?

UserModel

    import 'package:cloud_firestore/cloud_firestore.dart';
    import 'package:flutter/foundation.dart';

    class UserModel {

      final String id;
      final String phoneNumber;
      final String name;

      UserModel._internal({
        @required this.id,
        @required this.phoneNumber,
        @required this.name,
      })  : assert(id != null),
      assert(phoneNumber != null),
      assert(name != null);

      factory UserModel.fromFirebase(DocumentSnapshot snapshot)
      {
        return UserModel._internal(
          id: snapshot.documentID ?? '',
//snapshot is a stream so this will be async which is not nice. Should I map both public and private into one usermodel somehow?
          phoneNumber: snapshot.reference.collection('public').document('data'). ?? '',
//snapshot is a stream so this will be async which is not nice. Should I map both public and private into one usermodel somehow?
          name: snapshot.reference.collection('public').document('data').  ?? '',
        );
      }

    }

UserProvider

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:app_name/data/models/user_authentication_certificate.dart';
import 'package:app_name/data/models/user_model.dart';

class UserProvider {
  static const userCollectionKey = 'users';
  final CollectionReference userCollection =
      Firestore.instance.collection(userCollectionKey);

  Stream<UserModel> me(UserAuthenticationCertificate certificate) {
    return userCollection.document(certificate.userID).snapshots().map((snapshot) =>
        UserModel.fromFirebase(snapshot));
  }
}

Редактировать

Я думал, что решил эту проблему, сжав потоки. Но, как выясняется, он излучает только тогда, когда каждый поток изменился. Любое решение для этого?

  Stream<UserModel> me(UserAuthenticationCertificate certificate) {
    Stream<DocumentSnapshot> userData = userCollection.document(certificate.userID).snapshots();
    Stream<DocumentSnapshot> privateUserData = userCollection.document(certificate.userID).collection('private').document('data').snapshots();
    Stream<DocumentSnapshot> publicUserData = userCollection.document(certificate.userID).collection('public').document('data').snapshots();
    return StreamZip([userData, privateUserData, publicUserData]).asBroadcastStream().map((snapshot) => UserModel.fromFirebase(snapshot));
  }

Ответы [ 2 ]

1 голос
/ 24 марта 2020

Вы можете объединить оба потока, используя MergeStream из RxDart, здесь есть ссылка на документы

https://pub.dev/documentation/rxdart/latest/rx/MergeStream-class.html

и здесь другая ссылка, чтобы понять, как это работает

https://rxmarbles.com/#merge

0 голосов
/ 24 марта 2020

Я использовал rxdart для использования CombineLatestStream, который делает именно то, что мне нужно!

import 'package:rxdart/rxdart.dart';
import 'dart:async';

  Stream<UserModel> me(UserAuthenticationCertificate certificate) {
    Stream<DocumentSnapshot> userData = userCollection.document(certificate.userID).snapshots();
    Stream<DocumentSnapshot> privateUserData = userCollection.document(certificate.userID).collection('private').document('data').snapshots();
    Stream<DocumentSnapshot> publicUserData = userCollection.document(certificate.userID).collection('public').document('data').snapshots();
    return CombineLatestStream([userData, privateUserData, publicUserData], (values) => values.toList()).asBroadcastStream().map((snapshot) => UserModel.fromFirebase(snapshot));
  }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...