如何在Firestore中随机选取两名用户并创建聊天室?
随机用户匹配与聊天室实现方案
一、匹配逻辑
方案1:直接随机选取(适合初期小规模用户)
- 从
users集合中排除当前登录用户 - 随机获取一个目标用户(若需匹配两名任意用户,则排除系统用户后选两个)
- 可选:检查双方是否已有活跃聊天室,避免重复匹配
方案2:等待队列机制(适合用户量较大场景)
- 维护
waiting_queue集合,用户点击匹配时加入队列 - 实时监听队列,当队列中有≥2个用户时,取出前两名进行匹配
- 匹配完成后将这两名用户从队列移除
二、Firestore聊天室创建实现(Flutter代码)
1. 直接随机匹配并创建聊天室
import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:firebase_auth/firebase_auth.dart'; Future<void> createRandomChatRoom() async { final firestore = FirebaseFirestore.instance; final currentUser = FirebaseAuth.instance.currentUser; if (currentUser == null) { throw Exception('请先登录'); } // 1. 查询排除当前用户的所有用户 final usersQuery = await firestore.collection('users') .where(FieldPath.documentId, isNotEqualTo: currentUser.uid) .get(); if (usersQuery.docs.isEmpty) { throw Exception('暂无其他用户可匹配'); } // 2. 随机选取一个匹配用户 final userList = usersQuery.docs; userList.shuffle(); final matchedUserDoc = userList[0]; final matchedUserUid = matchedUserDoc.id; // 3. 生成唯一聊天室ID(按UID排序拼接,避免重复创建) final memberUids = [currentUser.uid, matchedUserUid]..sort(); final chatRoomId = memberUids.join('_'); // 4. 创建聊天室主文档 await firestore.collection('rooms').doc(chatRoomId).set({ 'members': memberUids, 'createdAt': FieldValue.serverTimestamp(), 'lastMessage': '', 'lastMessageTime': FieldValue.serverTimestamp(), 'memberInfo': { currentUser.uid: { 'username': currentUser.displayName ?? '匿名用户', 'gender': await _getCurrentUserGender() }, matchedUserUid: matchedUserDoc.data() } }); // 5. 初始化系统欢迎消息(可选) await firestore.collection('rooms').doc(chatRoomId) .collection('messages') .add({ 'senderId': 'system', 'content': '欢迎开始聊天!', 'timestamp': FieldValue.serverTimestamp() }); // 6. 结合flyer chat包初始化聊天会话 // FlyerChat.instance.initRoom(chatRoomId, members: memberUids); } // 示例:获取当前用户性别 Future<String?> _getCurrentUserGender() async { final currentUid = FirebaseAuth.instance.currentUser!.uid; final userDoc = await FirebaseFirestore.instance.collection('users').doc(currentUid).get(); return userDoc.data()?['gender']; }
2. 等待队列式匹配实现
Future<void> joinMatchQueue() async { final firestore = FirebaseFirestore.instance; final currentUser = FirebaseAuth.instance.currentUser; if (currentUser == null) { throw Exception('请先登录'); } // 加入等待队列 await firestore.collection('waiting_queue').doc(currentUser.uid).set({ 'joinedAt': FieldValue.serverTimestamp(), 'uid': currentUser.uid, 'username': currentUser.displayName ?? '匿名用户', 'gender': await _getCurrentUserGender() }); // 监听队列变化,触发匹配 final queueListener = firestore.collection('waiting_queue').snapshots().listen((snapshot) async { if (snapshot.docs.length >= 2) { // 取出队列前两名用户 final user1Doc = snapshot.docs[0]; final user2Doc = snapshot.docs[1]; final user1Uid = user1Doc.id; final user2Uid = user2Doc.id; // 生成唯一聊天室ID final memberUids = [user1Uid, user2Uid]..sort(); final chatRoomId = memberUids.join('_'); // 创建聊天室 await firestore.collection('rooms').doc(chatRoomId).set({ 'members': memberUids, 'createdAt': FieldValue.serverTimestamp(), 'memberInfo': { user1Uid: user1Doc.data(), user2Uid: user2Doc.data() } }); // 从队列移除已匹配用户 await firestore.collection('waiting_queue').doc(user1Uid).delete(); await firestore.collection('waiting_queue').doc(user2Uid).delete(); // 停止监听,避免重复触发 queueListener.cancel(); // 跳转至聊天界面(示例) // Navigator.push(context, MaterialPageRoute(builder: (_) => ChatRoomScreen(roomId: chatRoomId))); } }); }
三、核心注意事项
- 唯一聊天室ID:通过排序UID拼接生成,确保同一对用户不会重复创建聊天室
- 并发安全:推荐使用Firestore事务或云函数处理队列匹配,防止多客户端同时操作导致的重复匹配
- 用户状态优化:在
users集合添加isOnline字段,匹配时优先筛选在线用户,提升体验 - 异常处理:添加网络、权限等异常捕获,给用户清晰的错误提示
内容的提问来源于stack exchange,提问作者cipano
相关产品推荐
相关产品推荐

