iOS扑克项目Firebase数据模型结构设计合理性咨询
扑克项目Firebase数据模型设计优化建议
问题1:现有设计路径合理性与查询支持
现有设计路径合理,完全可以支持你当前提的所有查询需求:
- 你将玩家信息从Table文档的数组调整为Table下的Players子集合的操作非常正确,规避了Firestore对数组字段查询能力弱的短板。
- 最近牌桌页的需求可以直接通过对
Tables根集合执行whereArrayContains("playerIDs", 当前用户UID)查询实现,无需额外关联其他集合。 - 牌桌详情、手牌详情的查询逻辑也完全匹配你当前的嵌套子集合结构,没有多余的查询开销。
小优化点:建议在Users根集合的对应用户文档中,冗余存储最近10~20条参与过的牌桌ID数组,首次加载最近牌桌页时直接批量获取对应Table文档,查询速度比条件检索更快,尤其用户历史参与牌桌数量较多时体验提升明显。
问题2:Rounds是否调整为对象数组存储在Hand文档中
非常建议保留现有设计,将Rounds、Action都作为嵌套对象数组存在Hand文档内,由客户端解析即可:
- 单条Hand文档的大小远低于Firestore单文档1MB的上限,即使是10人桌多轮次对局的手牌,单文档大小通常也只有几KB,完全没有存储超限风险。
- 查看手牌详情页时本就需要加载整副手牌的所有轮次、操作记录,单文档读取仅需1次读请求,相比拆分Rounds、Action为子集合的方案,请求成本更低、加载速度更快,客户端解析嵌套结构的开销远低于多次网络请求的开销。
问题3:是否将Hand集合调整为根集合
取决于你后续的功能规划,当前需求下无需调整:
- 若无「跨所有牌桌查询满足特定条件的手牌」(比如查询某用户所有赢过的手牌、所有Allin获胜的手牌)这类全局检索Hand的需求,Hand作为Table的子集合是更优选择:查询某桌所有手牌时直接检索对应子集合即可,无需额外添加tableID过滤条件,权限控制也更简单,直接设置仅牌桌参与玩家可访问该Table下的Hands子集合即可。
- 若后续需要实现全局手牌检索的功能,可选择两种方案:一是将Hand提升为根集合,每个Hand文档冗余存储tableID、参与玩家ID数组等过滤字段;二是在Users文档下冗余存储该用户参与过的所有HandID及对应tableID,需要查询时批量获取即可,无需调整整体结构。
额外优化建议
- 建议在Table下的Players子集合的单玩家文档中,冗余存储该玩家在当前桌的总盈利、参与手牌数、胜率等统计字段,打开牌桌详情页时直接读取即可,无需每次遍历所有Hand文档计算,大幅降低请求次数。
- 你当前Hand文档中存储对局时的玩家快照信息的设计非常合理,避免后续玩家修改昵称、头像后,历史手牌记录中的信息同步变化的问题,无需调整。
- 现有嵌套存储的结构对Firestore离线缓存的适配性更好,若后续要做离线查看历史对局的功能,无需额外适配即可实现。
内容的提问来源于stack exchange,提问作者DaveAmerica
相关产品推荐
相关产品推荐

