You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Firestore中基于好友投票的菜品排名查询与数据结构设计

实现按好友投票数的菜品排名方案

数据结构调整

1. 优化现有集合结构

  • Dishes集合:保留原有字段,若原votes字段已存储所有投票用户ID则直接复用,否则新增votedUserIds数组存储该内容。
  • Users集合:每个用户文档新增两个字段:
    • friends:数组,存储当前用户的所有好友ID(已有则无需新增)。
    • dishFriendVoteCounts:Map类型(键为dish_id,值为数字),记录当前用户的好友对各菜品的投票总数。
    • votedDishes:数组,存储当前用户投票过的所有菜品ID(用于好友关系变更时批量更新计数)。

2. 写操作同步逻辑

当发生投票或好友关系变更时,需同步更新计数:

  • 用户投票时:
    1. 给目标菜品的votes(或votedUserIds)数组添加当前用户ID。
    2. 将该菜品ID添加到当前用户的votedDishes数组。
    3. 获取当前用户的所有好友列表,遍历每个好友的文档,将dishFriendVoteCounts中对应菜品的计数+1(无则设为1)。
  • 添加好友时:
    1. 将新好友ID添加到当前用户的friends数组。
    2. 获取新好友的votedDishes列表,遍历每个菜品ID,将当前用户的dishFriendVoteCounts中对应菜品的计数+1(无则设为1)。

查询实现步骤

方式一:预计算计数(高性能,推荐大数据量场景)

// 1. 获取当前用户的好友投票计数
const currentUserRef = doc(db, 'users', CURRENT_USER_ID);
const currentUserDoc = await getDoc(currentUserRef);
const dishFriendVoteCounts = currentUserDoc.data().dishFriendVoteCounts || {};

// 2. 查询所有汤类菜品
const dishRef = collection(db, 'dishes');
const q = query(dishRef, where('categories', 'array-contains', 'Soup'));
const dishesSnapshot = await getDocs(q);

// 3. 匹配计数并排序
const rankedDishes = dishesSnapshot.docs.map(doc => {
  const dishData = doc.data();
  return {
    ...dishData,
    id: doc.id,
    friendVoteCount: dishFriendVoteCounts[dishData.dish_id] || 0
  };
}).sort((a, b) => b.friendVoteCount - a.friendVoteCount);

方式二:实时计算(适合小数据量场景,无需修改写逻辑)

如果菜品数量少、投票数不多,可直接在客户端计算好友投票数:

// 1. 获取当前用户的好友列表
const currentUserDoc = await getDoc(doc(db, 'users', CURRENT_USER_ID));
const currentUserFriends = currentUserDoc.data().friends || [];

// 2. 查询所有汤类菜品
const q = query(collection(db, 'dishes'), where('categories', 'array-contains', 'Soup'));
const dishesSnapshot = await getDocs(q);

// 3. 计算好友投票数并排序
const rankedDishes = dishesSnapshot.docs.map(doc => {
  const dishData = doc.data();
  const friendVoteCount = (dishData.votes || []).filter(userId => currentUserFriends.includes(userId)).length;
  return { ...dishData, id: doc.id, friendVoteCount };
}).sort((a, b) => b.friendVoteCount - a.friendVoteCount);

是否需要新增集合?

不需要新增集合,仅需调整现有users和dishes集合的文档结构即可。若希望投票记录更结构化,也可给每个菜品新增votes子集合(每个文档存单个投票的用户ID、时间等),但这不是必须项,视业务复杂度决定。

内容的提问来源于stack exchange,提问作者Thanh Le

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 14:45:24