How do I join data from two Firestore collections in Flutter?

前端 未结 6 860
名媛妹妹
名媛妹妹 2020-11-29 02:27

I have a chat app in Flutter using Firestore, and I have two main collections:

  • chats, which is keyed on auto-ids, and has message,
6条回答
  •  野趣味
    野趣味 (楼主)
    2020-11-29 02:54

    Allow me to put forth my version of an RxDart solution. I use combineLatest2 with a ListView.builder to build each message Widget. During the construction of each message Widget I lookup the name of the user with the corresponding uid.

    In this snippet I use a linear lookup for the user's name but that can be improved by creating a uid -> user name map

    import 'package:cloud_firestore/cloud_firestore.dart';
    import 'package:flutter/widgets.dart';
    import 'package:rxdart/rxdart.dart';
    
    class MessageWidget extends StatelessWidget {
      // final chatStream = Firestore.instance.collection('chat').snapshots();
      // final userStream = Firestore.instance.collection('users').snapshots();
      Stream chatStream;
      Stream userStream;
    
      MessageWidget(this.chatStream, this.userStream);
    
      @override
      Widget build(BuildContext context) {
        Observable> combinedStream = Observable.combineLatest2(
            chatStream, userStream, (messages, users) => [messages, users]);
    
        return StreamBuilder(
            stream: combinedStream,
            builder: (_, AsyncSnapshot> snapshots) {
              if (snapshots.hasData) {
                List chats = snapshots.data[0].documents;
    
                // It would be more efficient to convert this list of user documents
                // to a map keyed on the uid which will allow quicker user lookup.
                List users = snapshots.data[1].documents;
    
                return ListView.builder(itemBuilder: (_, index) {
                  return Center(
                    child: Column(
                      children: [
                        Text(chats[index]['message']),
                        Text(getUserName(users, chats[index]['uid'])),
                      ],
                    ),
                  );
                });
              } else {
                return Text('loading...');
              }
            });
      }
    
      // This does a linear search through the list of users. However a map
      // could be used to make the finding of the user's name more efficient.
      String getUserName(List users, String uid) {
        for (final user in users) {
          if (user['uid'] == uid) {
            return user['name'];
          }
        }
        return 'unknown';
      }
    }
    

提交回复
热议问题