Firestore 集合查询作为 Flutter 中的流

Sim*_*rtM 5 stream firebase flutter google-cloud-firestore

我正在尝试从集合中查询一些文档,此查询应该侦听在查询文档中所做的更改,因此我需要一个流。我正在关注(在 Dart/Flutter 中)

  Stream<List<MatchRequest>> _getNewMatches() {
    return Collection<MatchRequest>(path: 'requests')
        .ref
        .where('status', isNull: true)
        .where('users', arrayContains: ['$currentUid'])
        .orderBy('last_activity')
        .snapshots()
        .map((list) => list.documents.map(
            (doc) => Global.models[MatchRequest](doc.data) as MatchRequest));
  }
Run Code Online (Sandbox Code Playgroud)

(对象 Collection 在它的构造函数中设置 ref 的路径,例如:ref = db.collection($path) 并且地图制作结果模型)

然后我使用 StreamBuilderstream调用上面的方法并builder检查快照.hasData 。但它一直在加载,snapshot.hasData 一直是假的。我在这里做错了什么?

编辑:

  1. 我的 Firestore 安全规则包含:

    match /requests/{requestId} {
        allow read: if isLoggedIn();
        allow write: if isLoggedIn();
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 删除每个where和时orderBy,它也找不到任何东西。并且请求集合中存在文档

  3. 当尝试从请求集合中仅查询 1 个文档作为流时,他确实找到了结果

  4. 是因为我应该向 Firestore 索引添加索引吗?但这并不能解决我的第一个问题,即即使没有whereand orderBy,它也不会获得任何数据

Joã*_*res 8

我写了一个简单的例子,它似乎就像你想要做的,但缺少 listen() 方法:

Firestore.instance.collection('collection')
  .where('field', isEqualTo: 'value')
  .orderBy('field')
  .snapshots()
  .listen((QuerySnapshot querySnapshot){
    querySnapshot.documents.forEach((document) => print(document));
  }
);
Run Code Online (Sandbox Code Playgroud)

这只是一个示例,说明如何从 Firestore Stream 获取数据并在 StreamBuilder 上使用它:

class _MyHomePageState extends State<MyHomePage> {
  Stream dataList;

  @override
  void initState() {
    dataList = Firestore.instance.collection('collection')
      .where('field', isEqualTo: 'value')
      .orderBy('field')
      .snapshots();

    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: StreamBuilder(
          stream: dataList,
          builder: (context, asyncSnapshot) {
            if(asyncSnapshot.hasError)
              return Text('Error: ${asyncSnapshot.error}');

            switch (asyncSnapshot.connectionState) {
              case ConnectionState.none: return Text('No data');
              case ConnectionState.waiting: return Text('Awaiting...');
              case ConnectionState.active:
                return ListView(
                  children: asyncSnapshot.data.map((document) => Text(document['value'])),
                );
              break;
              case ConnectionState.done: return ListView(
                children: asyncSnapshot.data.map((document) => Text(document['value'])),
              );
              break;
            }
            return null;
        }),
      ),
    );
  }

} 
Run Code Online (Sandbox Code Playgroud)