如何在 Firebase 颤振应用程序中合并两个集合?

Posted

技术标签:

【中文标题】如何在 Firebase 颤振应用程序中合并两个集合?【英文标题】:How to merge two collections in Firebase flutter application? 【发布时间】:2020-06-03 05:18:39 【问题描述】:

我使用颤振创建了一个聊天应用程序并将数据存储在 Firebase 中。Firebase 包含两个集合。一个集合包含用户详细信息,另一个集合包含用户与其他用户的聊天。我想合并两个集合详细信息。如何获取其他存储在用户集合中的用户详细信息? 我附上了截图。 Firebase collection Flutter code

【问题讨论】:

Firestore 中没有“加入”类型的查询。您必须分别查询每个集合并在客户端应用程序中合并数据。 【参考方案1】:

我在我的应用程序中实现了相同的功能。我所做的是我两次使用 Streambuilder 小部件,一次拉聊天,每个聊天都包含一个 sender_id,然后我使用第二个 Stream builder 中的 Id 来拉用户信息。 检查下面的代码。这是所有聊天页面:

@override
  Widget build(BuildContext context) 
    return StreamBuilder(
      stream: FirebaseFirestore.instance
          .collection('MyChatHeads')
          .doc(_onlineUserId)
          .collection('Heads')
          .orderBy('head_time', descending: true)
          .snapshots(),
      builder: (context, snapshot) 
        if (!snapshot.hasData) 
          return Scaffold(
            body: Center(
              child: SpinKitThreeBounce(
                color: Colors.black54,
                size: 20.0,
              ),
            ),
          );
         else 
          if (snapshot.data.documents.length == 0) 
            return Scaffold(
              body: placeHolder(),
            );

            placeHolder();
           else 
            return Scaffold(
              floatingActionButton: FloatingActionButton(
                onPressed: () 
                  Navigator.push(
                    context,
                    CupertinoPageRoute(
                      builder: (_) => SearchUsersPage(
                        userId: _onlineUserId,
                      ),
                    ),
                  );
                ,
                child: Icon(Icons.contacts_rounded),
                foregroundColor: Colors.white,
                backgroundColor: Color(0xff47c8b0),
              ),
              body: ListView.builder(
                itemCount: snapshot.data.documents.length,
                itemBuilder: (context, index) 
                  DocumentSnapshot myChatHeads = snapshot.data.documents[index];
                  return chatHeadItem(
                      index, myChatHeads, snapshot.data.documents.length);
                ,
              ),
            );
          
        
      ,
    );
  



所有聊天页面中的项目

Widget chatHeadItem(int index, DocumentSnapshot myChatHeads, int length) 
    return StreamBuilder(
      stream: FirebaseFirestore.instance
          .collection('Users')
          .where('user_id', isEqualTo: myChatHeads['head_subject'])
          .snapshots(),
      builder: (context, snapshot) 
        if (!snapshot.hasData) 
          return Center(
            child: SpinKitThreeBounce(
              color: Colors.black54,
              size: 20.0,
            ),
          );
         else 
          if (snapshot.data.documents.length == 0) 
            return Container(
              child: Padding(
                padding: const EdgeInsets.symmetric(
                  horizontal: 16.0,
                ),
                child: Row(
                  children: [
                    CircleAvatar(
                      radius: 30,
                      backgroundColor: Colors.green,
                      child: CircleAvatar(
                        radius: 28,
                        backgroundColor: Colors.white,
                        child: Image(
                          height: 56,
                          width: 56,
                          image: AssetImage('assets/images/holder.png'),
                          fit: BoxFit.cover,
                        ),
                      ),
                    ),
                    SizedBox(
                      width: 10,
                    ),
                    Flexible(
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: <Widget>[
                          SizedBox(
                            height: 10,
                          ),
                          Text(
                            'User not found',
                            style: GoogleFonts.quicksand(
                              color: Colors.black87,
                              fontWeight: FontWeight.bold,
                              fontSize: 16.0,
                              letterSpacing: .5,
                            ),
                          ),
                          //setCompanyName(myInterviews),
                          SizedBox(
                            height: 4.0,
                          ),
                          InkWell(
                            onTap: () 
                              Navigator.push(
                                context,
                                CupertinoPageRoute(
                                  builder: (_) => ChatsEngagePage(
                                    userId: _onlineUserId,
                                    secondUserId: myChatHeads['head_subject'],
                                  ),
                                ),
                              );
                            ,
                            child: Text(
                              '$myChatHeads['head_last_message']',
                              maxLines: 2,
                              overflow: TextOverflow.ellipsis,
                              style: GoogleFonts.quicksand(
                                color: Colors.black87,
                                fontSize: 16.0,
                                letterSpacing: .5,
                              ),
                            ),
                          ),
                          SizedBox(
                            height: 10,
                          ),
                        ],
                      ),
                    ),
                  ],
                ),
              ),
            );
           else 
            DocumentSnapshot secondUserInfo = snapshot.data.documents[0];
            return Container(
              //color: Colors.green,
              child: Padding(
                padding: const EdgeInsets.symmetric(
                  horizontal: 16.0,
                ),
                child: Column(
                  children: [
                    index == 0
                        ? SizedBox(
                            height: 6,
                          )
                        : SizedBox(
                            height: 0,
                          ),
                    InkWell(
                      onTap: () 
                        Navigator.push(
                          context,
                          CupertinoPageRoute(
                            builder: (_) => ChatsEngagePage(
                              userId: _onlineUserId,
                              secondUserId: myChatHeads['head_subject'],
                              userName: secondUserInfo['user_name'],
                              userImage: secondUserInfo['user_image'],
                            ),
                          ),
                        );
                      ,
                      child: Row(
                        children: [
                          InkWell(
                            onTap: () 
                              Navigator.push(
                                context,
                                CupertinoPageRoute(
                                  builder: (_) => PublicProfilePage(
                                    userId: _onlineUserId,
                                    secondUserId: secondUserInfo['user_id'],
                                  ),
                                ),
                              );
                            ,
                            child: CachedNetworkImage(
                              imageUrl: secondUserInfo['user_image'],
                              imageBuilder: (context, imageProvider) =>
                                  CircleAvatar(
                                radius: 30,
                                backgroundColor: Colors.green,
                                child: CircleAvatar(
                                  radius: 28,
                                  backgroundColor: Colors.white,
                                  backgroundImage: imageProvider,
                                ),
                              ),
                              placeholder: (context, url) => CircleAvatar(
                                radius: 30,
                                backgroundColor: Colors.green,
                                child: CircleAvatar(
                                  radius: 28,
                                  backgroundColor: Colors.white,
                                  backgroundImage: AssetImage(
                                    'assets/images/holder.png',
                                  ),
                                ),
                              ),
                              errorWidget: (context, url, error) =>
                                  CircleAvatar(
                                radius: 30,
                                backgroundColor: Colors.green,
                                child: CircleAvatar(
                                  radius: 28,
                                  backgroundColor: Colors.white,
                                  backgroundImage: AssetImage(
                                    'assets/images/holder.png',
                                  ),
                                ),
                              ),
                            ),
                          ),
                          SizedBox(
                            width: 10,
                          ),
                          Flexible(
                            child: Column(
                              crossAxisAlignment: CrossAxisAlignment.start,
                              children: <Widget>[
                                SizedBox(
                                  height: 10,
                                ),
                                Row(
                                  mainAxisAlignment:
                                      MainAxisAlignment.spaceBetween,
                                  children: [
                                    Flexible(
                                      child: Text(
                                        '$secondUserInfo['user_name']',
                                        style: GoogleFonts.quicksand(
                                          color: Colors.black87,
                                          fontWeight: FontWeight.bold,
                                          fontSize: 16.0,
                                          letterSpacing: .5,
                                        ),
                                        maxLines: 1,
                                        overflow: TextOverflow.ellipsis,
                                      ),
                                    ),
                                    Text(
                                      timeAgoSinceDateEn(
                                        DateTime.fromMillisecondsSinceEpoch(
                                          myChatHeads['head_time'],
                                        ).toString(),
                                      ),
                                      //postSnap['press_formatted_date'],
                                      style: GoogleFonts.quicksand(
                                        textStyle: TextStyle(
                                          fontSize: 14.0,
                                          color: Colors.grey,
                                        ),
                                      ),
                                    ),
                                  ],
                                ),
                                //setCompanyName(myInterviews),
                                SizedBox(
                                  height: 4.0,
                                ),
                                Text(
                                  '$myChatHeads['head_last_message']',
                                  maxLines: 2,
                                  overflow: TextOverflow.ellipsis,
                                  style: GoogleFonts.quicksand(
                                    color: Colors.black87,
                                    fontSize: 16.0,
                                    letterSpacing: .5,
                                  ),
                                ),
                                SizedBox(
                                  height: 10,
                                ),
                              ],
                            ),
                          ),
                        ],
                      ),
                    ),
                    index == length - 1
                        ? Container()
                        : Divider(
                            //color: Colors.red,
                            ),
                    index == length - 1
                        ? SizedBox(
                            height: 4,
                          )
                        : SizedBox(
                            height: 0,
                          ),
                  ],
                ),
              ),
            );
          
        
      ,
    );
  

这是一个单独的聊天页面:

body: Stack(
        children: [
          Container(
            height: double.infinity,
            width: double.infinity,
            color: Colors.grey[100],
            child: StreamBuilder(
              stream: FirebaseFirestore.instance
                  .collection('Chats')
                  .doc(userId)
                  .collection(secondUserId)
                  .orderBy('message_time', descending: true)
                  .snapshots(),
              builder: (context, snapshot) 
                if (!snapshot.hasData) 
                  return Center(
                    child: Padding(
                      padding: const EdgeInsets.symmetric(vertical: 16),
                      child: SpinKitThreeBounce(
                        color: Colors.black54,
                        size: 20.0,
                      ),
                    ),
                  );
                 else 
                  if (snapshot.data.documents.length == 0) 
                    return Center(
                      child: Padding(
                        padding: const EdgeInsets.symmetric(vertical: 16),
                        child: Container(
                          width: MediaQuery.of(context).size.width / 3,
                          child: Image(
                            image: AssetImage('assets/images/empty.png'),
                            width: double.infinity,
                          ),
                        ),
                      ),
                    );
                   else 
                    return Padding(
                      padding: const EdgeInsets.symmetric(horizontal: 8.0),
                      child: ListView.builder(
                        shrinkWrap: true,
                        reverse: true,
                        // physics: NeverScrollableScrollPhysics(),
                        // primary: false,
                        padding: EdgeInsets.zero,
                        itemCount: snapshot.data.documents.length,
                        itemBuilder: (context, index) 
                          DocumentSnapshot myPresses =
                              snapshot.data.documents[index];
                          if (myPresses['message_owner'] == userId) 
                            return Padding(
                              padding: index == 0
                                  ? EdgeInsets.only(bottom: height + 26)
                                  : EdgeInsets.only(bottom: 0),
                              child: Bubble(
                                margin: BubbleEdges.only(top: 10),
                                nip: BubbleNip.rightTop,
                                alignment: Alignment.topRight,
                                color: Colors.lightGreen[100],
                                child: Column(
                                  crossAxisAlignment: CrossAxisAlignment.end,
                                  children: [
                                    Text(
                                      myPresses['message_body'],
                                      style: GoogleFonts.quicksand(
                                        fontSize: 16,
                                        color: Colors.black87,
                                      ),
                                    ),
                                    Text(
                                      timeAgoSinceDateEn(
                                        DateTime.fromMillisecondsSinceEpoch(
                                          myPresses['message_time'],
                                        ).toString(),
                                      ),
                                      //postSnap['press_formatted_date'],
                                      style: GoogleFonts.quicksand(
                                        textStyle: TextStyle(
                                          fontSize: 14.0,
                                          color: Colors.grey,
                                        ),
                                      ),
                                    ),
                                  ],
                                ),
                              ),
                            );
                           else 
                            return Padding(
                              padding: index == 0
                                  ? EdgeInsets.only(bottom: height + 26)
                                  : EdgeInsets.only(bottom: 0),
                              child: Bubble(
                                margin: BubbleEdges.only(top: 10),
                                alignment: Alignment.topLeft,
                                nip: BubbleNip.leftTop,
                                color: Color(0xffd4eaf5),
                                child: Column(
                                  crossAxisAlignment: CrossAxisAlignment.end,
                                  children: [
                                    Text(
                                      myPresses['message_body'],
                                      style: GoogleFonts.quicksand(
                                        fontSize: 16,
                                        color: Colors.black87,
                                      ),
                                    ),
                                    Text(
                                      timeAgoSinceDateEn(
                                        DateTime.fromMillisecondsSinceEpoch(
                                          myPresses['message_time'],
                                        ).toString(),
                                      ),
                                      //postSnap['press_formatted_date'],
                                      style: GoogleFonts.quicksand(
                                        textStyle: TextStyle(
                                          fontSize: 14.0,
                                          color: Colors.grey,
                                        ),
                                      ),
                                    ),
                                  ],
                                ),
                              ),
                            );
                          
                        ,
                      ),
                    );
                  
                
              ,
            ),
          ),
          Positioned(
            bottom: 10.0,
            left: 10.0,
            right: 10.0,
            child: MeasuredSize(
              onChange: (Size size) 
                setState(() 
                  print(size);
                  height = size.height;
                );
              ,
              child: Container(
                decoration: BoxDecoration(
                  color: Colors.white,
                  borderRadius: BorderRadius.all(
                    Radius.circular(0),
                  ),
                  boxShadow: [
                    BoxShadow(
                      color: Colors.grey.withOpacity(0.4),
                      spreadRadius: 2,
                      blurRadius: 3,
                      offset: Offset(0, 2), // changes position of shadow
                    ),
                  ],
                ),
                //height: 58,
                child: Padding(
                  padding: const EdgeInsets.symmetric(
                      horizontal: 8.0, vertical: 8.0),
                  child: Row(
                    crossAxisAlignment: CrossAxisAlignment.end,
                    children: [
                      Expanded(
                        child: TextFormField(
                          controller: textEditingController,
                          keyboardType: TextInputType.multiline,
                          textCapitalization: TextCapitalization.sentences,
                          maxLength: 800,
                          maxLines: null,
                          style: GoogleFonts.quicksand(
                            textStyle: TextStyle(
                              fontSize: 14.0,
                              color: Colors.black54,
                              letterSpacing: .5,
                            ),
                          ),
                          decoration: InputDecoration(
                            labelText: 'Message',
                            contentPadding: const EdgeInsets.symmetric(
                                horizontal: 0.0, vertical: 0.0),
                            errorStyle: TextStyle(color: Colors.brown),
                          ),
                          onChanged: (val) 
                            setState(() => _message = val);
                          ,
                          validator: (val) =>
                              val.length < 1 ? ('Too short') : null,
                        ),
                      ),
                      SizedBox(
                        width: 16,
                      ),
                      InkWell(
                        onTap: () 
                          _submitMessage();
                        ,
                        child: Padding(
                          padding:
                              const EdgeInsets.only(right: 8.0, bottom: 20),
                          child: Icon(
                            Icons.send_rounded,
                            color: Colors.green,
                          ),
                        ),
                      ),
                    ],
                  ),
                ),
              ),
            ),
          ),
        ],
      ),

【讨论】:

以上是关于如何在 Firebase 颤振应用程序中合并两个集合?的主要内容,如果未能解决你的问题,请参考以下文章

Firebase 分析:在一个 firebase 项目中收集不同 ios 应用程序的分析数据 - 颤振

我需要有关使用 firebase 的颤振聊天应用程序的帮助

如何在颤振应用程序中使用相同的 Firebase 匿名用户

我想将 firebase 自定义模型集成到颤振应用程序中。我如何整合?

如何停止颤振应用程序中的firebase错误

如何在 FirebaseStorage 中使用 StreamBuilder 来通知我的应用我的 Firebase 存储发生变化?在颤振中